使用基类调用泛型不能从基类转换为T.

时间:2013-02-18 11:11:27

标签: c# generics

我有以下设置,似乎我的对象无法转换为泛型类型。虽然它实际上是基类。为什么这不起作用?这对我来说似乎很合乎逻辑。

public class AList<T> where T : A
{
    void DoStuff(T foo)
    {
    }

    void CallDoStuff()
    {
        DoStuff(new A()); // ERROR: Cannot convert A to T
    }
}

public class A
{
}

5 个答案:

答案 0 :(得分:3)

此处的问题是约束表明T必须是A 或来自A 的类。
现在,当您使用具体类型实例化AList时,T是一个非常具体的类。如果您没有使用AList本身A实例化T但是使用它的子类,Apublic class Animal { public int Foo { get; set; } } public class Cat : Animal { public int Bar { get; set; } } Derived d = new Base(); 的子类。

您无法将具有基类的运行时类型的实例转换为其子类之一,因为它错过了子类添加的所有信息。

示例:

Cat

您希望该代码有效吗?当然不是,因为Animal也是Animal,但Cat不是d.Bar = 42;。 如果您希望上述代码实际工作,请问自己在执行以下代码时应该发生什么:Animal
Bar不包含{{1}}的定义。

你的代码中也发生了同样的事情 - 游戏中的泛型更加模糊不清。

答案 1 :(得分:2)

T也可以是从A派生的类,因此您无法将A的实例作为T类型的参数。类似于调用方法的方法,它使用intobject类型的参数。

答案 2 :(得分:1)

这与object无法隐式转换为int的原因相同。

该方法需要一个子类,并且您正在传递父类,因此需要显式转换。

答案 3 :(得分:0)

因为你要求T扩展A.所以你可以用A替换T而不用T替换A.

如果Cat:Animal并不意味着您可以随时将动物转换为猫。

答案 4 :(得分:0)

尝试并使用Activator为您提供A T的实例,因为您知道由于您的约束,T必须是A,因此,您无需在new A()任意位置使用T,因此您只需创建T的实例。

T obj = Activator.CreateInstance<T>();
DoStuff(obj);

或者像其他答案所提到的那样对你的object进行演员表,但这并不适用于所有情况。

T obj = (T)new A();
DoStuff(obj);