Add in support for Enum and Delegate constraints
Currently C# disallows constraints for
System.Enum,
System.ValueType,
System.Delegate,
System.Array,
System.Object
However, the CLR has support for classes constrained to All 5 types.
It could be very useful to have this constrain.
To constraint a method to enum we can just use:
where T:struct,Enum
Allowing us to specify only to be called on enum instances and not those boxed as Enum.
Delegate is less strict unfortunately, as there is no way to specify that a T must be an inheritor of a class. A simple solution would be to add an interface to Delegate like `IDelegate` so that we can easily specify only invokable types.
Array is not really necessary as we can make the method have this signature:
MyMethod<T>(T[] array)...
Object is a useless constraint as everything that can be used as a generic argument parameter has to be assignable to system.object.
ValueType isn't necessary as you can use the struct constraint.
6 comments
-
SensorSmith commented
This was added in C# 7.3 (introduced enum, delegate, and unmanaged constraints)
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-7-3#enhanced-generic-constraintsSo... This should be closed as accepted/resolved.
-
David Burg commented
Would that include constraining a generic as nullable?
-
Keith Burgoyne commented
Supporting "where T : enum" for enums rather than "where T : struct" has been missing since forever. It would eliminate performance hits by removing the need for performing "typeof(T).GetTypeInfo().IsEnum" and then throwing an exception at runtime when the compiler should have just refused to accept the code at compile-time.
-
Anonymous commented
+1
Let's give some examples where this would be particular useful:
/// <summary>Typ safe Enum.Parse</summary>
public static E Parse<E>(string value)
where E : struct,IComparable,IConvertible,IFormattable
// where E : Enum required but invalid constraint
{ return (E)Enum.Parse(typeof(E), value);
}/// <summary>Get all enum values</summary>
public static E[] GetValues<E>()
where E : struct,IComparable,IConvertible,IFormattable
// where E : Enum required but invalid constraint
{ return (E[])Enum.GetValues(typeof(E));
}public static T CreateOpenInstanceDelegate<T>(this MethodInfo mi) where T : class
// where T : MulticastDelegate
{ ... }/// <summary>Create Proxy to call constructor by delegate</summary>
public static T CreateDelegate<T>(this ConstructorInfo ci) where T : class
// where T : MulticastDelegate
{ ... } -
Alex commented
This is allowed in cil. Jon skeet wrote a library which contains dummy types and a program that replaces the dummies with actual constraints. If someone wanted it badly enough to make that, just make it default.
-
Joshua A. Schaeffer commented
This is a no-brainer, I don't know why it doesn't get top votes considering how simple it is. Yes you can pass in a delegate as a generic parameter but it has to have a "class" constraint. And you can pass in an enum but it has to have a "struct" constraint. Inside the generic method though, there is no strong-typing against the delegate or the enum. There's no explainable reason for this.