我有以下设置,似乎我的对象无法转换为泛型类型。虽然它实际上是基类。为什么这不起作用?这对我来说似乎很合乎逻辑。
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
是一个非常具体的类。如果你没有AList
用A
它自己实例化,而是用它的一个子类实例化,那么它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
.
您的代码中也发生了同样的事情 - 它只是被游戏中的泛型所掩盖。
T
也可以是派生自的类,A
因此您不能将 instance ofA
作为 type 的参数T
。类似于调用方法的东西,它接受int
with 和 type 的参数object
。
object
这与无法int
隐式转换为的原因相同。
该方法需要一个子类,并且您正在传递父类,因此您需要显式强制转换。
因为您要求 T 扩展 A。所以您可以用 A 替换 T,但不能用 T 替换 A。
if Cat : Animal 并不意味着你总是可以将 Animal 转换为 Cat。
尝试并使用Activator
给你一个A
from的实例,T
因为你知道这T
必须是A
由于你的约束,所以不需要new A()
像你一样在任何地方使用T
,所以你可以只创建一个T
.
T obj = Activator.CreateInstance<T>();
DoStuff(obj);
或者像其他答案提到的那样做一个演员object
,但这并不适用于所有情况。
T obj = (T)new A();
DoStuff(obj);