Consider this trivial function:
public static bool IsPositive(IComparable<int> value)
{
return value.CompareTo(0) > 0;
}
Now, if I pass an int
to this method, it gets boxed. Wouldn't it therefore be better to define the above method as follows?
public static bool IsPositive<T>(T value) where T : IComparable<int>
{
return value.CompareTo(0) > 0;
}
Using a generic constraint in this way, I can achieve exactly the same functionality as the code above, with the added benefit that no boxing is necessary (since a call to IsPositive<int>
accepts a parameter of type int
).
The example code above is clearly quite pointless. But my broader question is: wouldn't it always make sense to define methods in the latter way (using a generic constraint rather than having a parameter of some interface type), to avoid the potential boxing of value types?
I suspect that the answer is likely to be "yes, but it requires more typing and in many cases encountering a value type will be very unlikely, such as when a method accepts some IEnumerable<T>
." But I'm wondering if there's a greater difference between these approaches that is escaping me at the moment.
Interface Type Constraint You can constrain the generic type by interface, thereby allowing only classes that implement that interface or classes that inherit from classes that implement the interface as the type parameter.
C# allows you to use constraints to restrict client code to specify certain types while instantiating generic types. It will give a compile-time error if you try to instantiate a generic type using a type that is not allowed by the specified constraints.
The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.
Multiple interface constraints can be specified. The constraining interface can also be generic.
One issue would be with the fact that the generic constrain isn't really part of the signature. If you have ...
static T Method<T>(T value) where T : ICompareable<int>
... and ...
static T Method<T>(T value) where T : IEnumerable<int>
... the compiler wouldn't have a way to know which is which.
And to invoke Eric Lippert...
Constraints are not part of the signature
A Generic Constraint Question
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With