为什么在泛型方法中,当类型参数被限制为实现T时,VS会警告我typeof(T)永远不是提供的类型?

20

我希望这个问题是正确的,所以让我们举个例子。想象一下以下通用方法:

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();

        // ...
    }
}

根据 MSDN,关键字 where 限制类型参数 T 的类型为 Base 或继承自此类。

[...] where 子句可以包括基类约束,它声明一个类型必须具有指定的类作为基类(或本身就是该类)才能用作该泛型类型的类型参数。

此代码也可以编译:

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

所以,当按照最后一个代码 typeof(T) 后,应该返回 Base,是吗?为什么 Visual Studio 还会向我输出此警告呢?

警告 CS0184:给定的表达式从未是提供的 ('Demo.Base') 类型。


你想做什么?确保 T 继承自 Base 是无用的,因为泛型约束已经确保了这一点。 - CodesInChaos
该约束条件确保 T 要么继承自 Base 或者 就是 Base 本身。我希望 T 只能从 Base 继承。 - Carsten
2个回答

27

typeof(whatever)总是返回Type类型的一个实例。 Type不是派生自Base

您需要的是这个:

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

看起来与之相同的东西是这样的:

if(variableOfTypeT is Base)

但是它有不同的含义。
第一个语句(使用 typeof(Base))只有当 TBase 时才为 true ,对于任何派生自 Base 的类型,它都将是 false
在您的类中,第二个语句(variableOfTypeT is Base)始终为 true,因为任何派生自 Base 的类都将返回其基类的检查结果为 true


1
替代方案不起作用... T 是一个类型参数,但被用作变量 ;) 但第一种方法可行... 我怎么会错过这个呢?!有时候解决方案太简单了 :D - Carsten

4

这不是检查继承关系的正确方法。

typeof(T)System.Type 类型,而不是 Base。要查看 T 是否派生自 Base,您应该使用 IsSubclassOf 方法,像这样:

if(typeof(T).IsSubclassOf(typeof(Base))  ... 

请注意,如果 T==Base,则将返回 false - CodesInChaos
我认为这就是重点。由于限制,OP已经知道T要么是基类,要么是派生类。 - zmbq
我想知道是否TBase,以确保只有该抽象类的实现才能传递到该方法。 IsSubclassOf将执行我已经用where约束表达的检查。 - Carsten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接