Why specifying a generic argument as interface is not an error with a class constraint?

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?

Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow