If I have a generic method like this one:
static void Foo<T>() where T : class
{
}
I could call it by specifying an interface type, for example ICollection<int>
Foo<ICollection<int>>();
Now assume I have a struct that implements ICollection<int>
:
struct Bar : ICollection<int>
I can't specify it explicitly as the type argument, but if I have a variable of type ICollection<int>
that has the underlying type Bar
, and change my generic method to take an argument of type T
, I can do:
static void Foo<T>(T arg) where T : class
{
}
ICollection<int> bar = new Bar();
Foo <ICollection<int>>(bar);
As you can see it completely ignores the generic constraint. So my question is why specifying an interface as a type argument is allowed when we have a class
constraint?
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.
Object, you'll apply constraints to the type parameter. For example, the base class constraint tells the compiler that only objects of this type or derived from this type will be used as type arguments. Once the compiler has this guarantee, it can allow methods of that type to be called in the generic class.
Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type. They declare capabilities that the type argument must have, and must be placed after any declared base class or implemented interfaces.
Only generic classes can implement generic interfaces. Normal classes can't implement generic interfaces.
The "class" constraint is really a "reference type" constraint - it doesn't specifically mean classes. (It works with delegate types too.) From the MSDN page on generic type constraints:
The type argument must be a reference type; this applies also to any class, interface, delegate, or array type.
Now for your example:
As you can see it completely avoids the generic constraint.
No it doesn't. It uses ICollection<int>
as the type argument, and that is a reference type. Note tha the value you're passing into the method is a reference, due to boxing.
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