Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

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.

like image 577
Carsten Avatar asked Feb 13 '13 13:02

Carsten


2 Answers

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.

like image 159
Daniel Hilgarth Avatar answered Oct 21 '22 02:10

Daniel Hilgarth


That's not how you check inheritance.

typeof(T) is of type System.Type, it's not Base. To see if T is derived from Base you should use the IsSubclassOf method, like this:

if(typeof(T).IsSubclassOf(typeof(Base))  ... 
like image 4
zmbq Avatar answered Oct 21 '22 04:10

zmbq