Multi-typed parameters (type unions) #3737
Replies: 3 comments
-
This sounds like something that could be solved by shapes/roles: #1711. Also, a related proposal is unions as their own kind of type: #399. |
Beta Was this translation helpful? Give feedback.
-
Sounds like a good case for source-generators. You write one version, add an annotation, and tehn your SG emits the overloads. |
Beta Was this translation helpful? Give feedback.
-
Support for unions of types in generics would be very useful and is something that people have asked for for many years. And with nullable reference types now supported that need is all the more obvious when we want to use Source generators likely are the only solution in the short term. The syntax would be ugly compared with it being built in to the language (so it's certainly not a good case; more a handy way of hacking a short-term solution). But it's something I have started working on (well more just thinking about at this stage) as a nuget package for when C# 9 is released. |
Beta Was this translation helpful? Give feedback.
-
Say you are creating a method designed to take an indexable sequence of homogenous values. At the moment, there are three types in the type hierarchy that represent this:
IList<T>
,IReadOnlyList<T>
, andReadOnlySpan<T>
. This means that if you for example are working on a library and you want to support the largest span of use cases, you have to overload this method for all 3 types, as they are mutually incompatible. Moreover, there will usually be no semantical difference between the overloads whatsoever, begging for impossible code reuse. And since there are some optimizations to handling arrays, you might also want to have an overload for arrays.In the simplest case:
I propose a way to unify these methods in the simplest way possible:
The idea is to have the compiler actually generate 4 methods from the same syntax tree, but each specialized for one of the unified types. Calling such a method should select the appropriate hidden overload, with one difference from normal overload resolution: if the type is ambiguous (for example when passing
List<T>
), the first viable match is selected, based on their order (IList<T>
in this case). The definition is invalid if there is already a method with the same signature as one of the specializations.The type of
collection
here is what could be called a "compile-time type union". It is permitted to use the intersection of the members of the unified type here, i.e. the method is valid only if it is valid for every specialized type of the unified. An exception to this rule could be temporarily "collapsing" the type to one of its unified type, for example in something likeif(collection is T[])
, similarly to howobject?
can collapse toobject
if the null value is tested.Additionally, generic parameters should be dropped in specializations where they become completely unused. For example:
This should become:
With this in mind, the arguably most powerful solution for the initial problem would be this:
Beta Was this translation helpful? Give feedback.
All reactions