5

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

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
{
}
4

5 回答 5

3

这里的问题是约束说T必须是A 或派生自的类A
现在,当您AList使用具体类型进行实例化时,T是一个非常具体的类。如果你没有AListA它自己实例化,而是用它的一个子类实例化,那么它T就是A.

您不能将具有基类的运行时类型的实例转换为其子类之一,因为它会丢失子类添加的所有信息。

例子:

public class Animal
{
    public int Foo { get; set; }
}

public class Cat : Animal
{
    public int Bar { get; set; }
}

Derived d = new Base();

您希望该代码能够正常工作吗?当然不是,因为 aCat也是 aAnimal但 aAnimal不是 a Cat
如果您希望上面的代码能够实际工作,请问问自己在执行以下代码时应该发生什么:d.Bar = 42;
Animal不包含Bar.

您的代码中也发生了同样的事情 - 它只是被游戏中的泛型所掩盖。

于 2013-02-18T11:16:04.277 回答
2

T也可以是派生自的类,A因此您不能将 instance ofA作为 type 的参数T。类似于调用方法的东西,它接受intwith 和 type 的参数object

于 2013-02-18T11:15:13.173 回答
1

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

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

于 2013-02-18T11:14:06.477 回答
0

因为您要求 T 扩展 A。所以您可以用 A 替换 T,但不能用 T 替换 A。

if Cat : Animal 并不意味着你总是可以将 Animal 转换为 Cat。

于 2013-02-18T11:15:29.670 回答
0

尝试并使用Activator给你一个Afrom的实例,T因为你知道这T必须是A由于你的约束,所以不需要new A()像你一样在任何地方使用T,所以你可以只创建一个T.

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

或者像其他答案提到的那样做一个演员object,但这并不适用于所有情况。

T obj = (T)new A();
DoStuff(obj);
于 2013-02-18T11:18:12.693 回答