C# 基类为的调用泛型无法从基类转换为T

C# 基类为的调用泛型无法从基类转换为T,c#,generics,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 { } 公共

我有以下设置,似乎我的对象无法转换为泛型类型。而它实际上是基类。为什么这样不行?在我看来,这是合乎逻辑的

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
{
}
公共类列表,其中T:A
{
空位(T-foo)
{
}
void CallDoStuff()
{
DoStuff(新A());//错误:无法将A转换为T
}
}
公共A类
{
}

这与
对象不能隐式转换为
int
的原因相同


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

T
也可以是从
a
派生的类,因此您不能将
a
的实例作为
T
类型的参数。类似于调用方法,它使用
int
和类型为
object
的参数,因为您要求T扩展A。因此可以用A替换T,但不能用T替换A


如果Cat:Animal,这并不意味着你总是可以将动物转换成Cat。

这里的问题是约束条件说
t
必须是
a
或从
a
派生的类
现在,当您用具体类型实例化
AList
时,
T
是一个非常特定的类。如果你没有用
A
本身实例化
AList
,而是用它的子类实例化,
t
A
的子类

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

例如:

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

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

Derived d = new Base();
您希望该代码正常工作吗?当然不是,因为猫也是动物,但是动物不是猫 如果您希望上面的代码能够实际工作,那么问问自己当执行以下代码时应该发生什么:
d.Bar=42
Animal
不包含
Bar
的定义


同样的情况也发生在你的代码中——游戏中的泛型稍微模糊了一点。

尝试使用
Activator
T
给你一个
a
的实例,因为你知道
T
必须是
a
,因为受你的限制,所以不需要使用
新的a()
只要您有
T
,就可以在任何地方创建
T
的实例

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

很好的逻辑,我会这样说,“如果猫:动物,它并不意味着任何动物都是猫”。好吧,这是有道理的。我只是忘记了,这种显式的键入要求我确保这里的所有对象都可以是of,而不是。所以,如果我想这样做,也许我不应该首先使用泛型。@Marnix:正确。如果您不想强制执行
a
的某个子类,但想同时允许所有子类和
a
本身:不要使用泛型。My+1因为有时,在我们可爱的C#语言中会出现一些错误,甚至会让我们看到新的(以及更进一步的)维度。
T obj = (T)new A();
DoStuff(obj);