Why does VS warn me that typeof(T) is never the provided type in a generic method where the type parameter is restricted to implement T?

Carsten picture Carsten · Feb 13, 2013 · Viewed 10.8k times · Source

I hope the question is correct, so let's give you an example. Imagine the following generic method:

public abstract class Base : IDisposable
{
    public static IEnumerable<T> GetList<T>()
        where T : Base
    {
        // To ensure T inherits from Base.
        if (typeof(T) is Base)
            throw new NotSupportedException();

        // ...
    }
}

According to the MSDN the keyword where restricts the type parameter T to be of type Base or to inherit from this class.

[...] a where clause can include a base class constraint, which states that a type must have the specified class as a base class (or be that class itself) in order to be used as a type argument for that generic type.

Also this code does compile:

public static T GetFirst()
    where T : Base
{
    // Call GetList explicitly using Base as type parameter.
    return (T)GetList<Base>().First();
}

So when following the last code typeof(T) should return Base, shouldn't it? Why does Visual Studio then prints this warning to me?

warning CS0184: The given expression is never of the provided ('Demo.Base') type.

Answer

Daniel Hilgarth picture Daniel Hilgarth · Feb 13, 2013

typeof(whatever) always returns an instance of type Type. Type doesn't derive from Base.

What you want is this:

if(typeof(T) == typeof(Base))
    throw new NotSupportedException("Please specify a type derived from Base");

Something that looks like it is the same is this:

if(variableOfTypeT is Base)

But that has a different meaning.
The first statement (with typeof(Base)) only is true if T is Base. It will be false for any type derived from Base.
The second statement (variableOfTypeT is Base) is always true in your class, because any class derived from Base will return true for a check for its base class.