带有基类give的调用泛型无法从基类转换为T
本文关键字:基类 转换 泛型 give 调用 | 更新日期: 2023-09-27 18:00:08
我有以下设置,并且我的对象似乎无法转换为泛型类型。而它实际上是基类。为什么不起作用?在我看来,这太合乎逻辑了。
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
或从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();
您希望该代码能够工作吗?当然不是,因为Cat
也是Animal
,但Animal
不是Cat
如果您希望上面的代码能够实际工作,请问问自己执行以下代码时应该发生什么:d.Bar = 42;
Animal
不包含Bar
的定义。
同样的情况也发生在你的代码中——只是游戏中的泛型稍微模糊了一点。
T
也可以是从A
派生的类,因此不能将A
的实例作为T
类型的参数。类似于调用方法,该方法使用int
和类型为object
的参数。
这与object
无法隐式转换为int
的原因相同。
该方法需要一个子类,而您正在传递父类,因此需要显式强制转换。
因为你要求T扩展A。所以你可以用A代替T,但不能用T代替A。
如果猫:动物,这并不意味着你总是可以把一只动物变成一只猫。
尝试使用Activator
从T
中为您提供A
的实例,因为您知道由于您的约束,T
必须是A
,所以不需要在任何地方使用new A()
,因为您有T
,所以您只需创建T
的实例。
T obj = Activator.CreateInstance<T>();
DoStuff(obj);
或者像其他答案提到的那样,对你的object
进行一次测试,但这并不是在所有情况下都有效。
T obj = (T)new A();
DoStuff(obj);