Proposal: Add Unions using a new Type #5002
Unanswered
mcintyre321
asked this question in
Language Ideas
Replies: 2 comments
-
dup of championed #113 |
Beta Was this translation helpful? Give feedback.
0 replies
-
@ufcpp I'll close this and add the content as comment to there |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Background
Although there are various improvements for pattern matching/switch improvements, there doesn't seem to be a proposal for adding Discriminated Union types (like those in f# / TypeScript) which provide exhaustive matching over a closed set of Types. In addition, the types in a OneOf union can be from any assembly, and don't require source access. e.g. you can have
OneOf<string, int, MyClass, SomeoneElsesClass>
It would be extremely useful to have this in c#, as it helps prevent a whole class of bugs (missed conditions/catches) and removes the need for certain types of boilerplate (e.g. return objects) and bad patterns (e.g. exceptions as control flow)
Problem
Adding this at the language level raises a lot of questions, e.g. how do you define a closed class hierarchy? Can it be done as succinctly as in F#?
Solution
The feature can be added fairly simply using a custom type, in the same way Tuple<T0, ..., TN> was added. It's not as pretty as in TypeScript, but it works:
I maintain a library, OneOf, which adds a OneOf<T0, ..., TN> type (although I've seen other proposals refer to an Option<T0, ..., TN> type) which has .Match(Func<T0, ..., TOut>, ..., Func<T0, ..., TOut> methods. By using implicit operators to create the OneOf instances from values, the syntax is very terse and ledgible.
The OneOf<T0, .., TN> type also provides
.Switch
and.TryGetTX(out TX value, out TRemainder remainer)
methods.Example of using a OneOf as a return value:
example of Matching
As new types are added to the OneOf definition, compiler errors are generated wherever the union is
Match
ed orSwitch
ed, as the methods are required to have the correct number of lambda parameters.If you've used DUs you will know that using these as return types e.g. public OneOf<User, InvalidName, NameTaken> CreateUser(string username) is really powerful as you can extend the types on the return type, and get a compiler warning in areas of the code which don't handle it, something you don't get with a switch or non-exhaustive pattern match.
This can be included in the BCL without language changes, although maybe
Union
would be a better name thanOneOf
(depends who the langauge is aimed at).There could be some language change too though, e.g. instead of
public OneOf<Foo, Bar> Baz()
, we could havepublic (Foo|Bar) Baz()
, or some improvements to matching. E.g. @jnm2 posted some ideas here.this proposal was originally made at dotnet/roslyn#14208
Beta Was this translation helpful? Give feedback.
All reactions