我有以下设置,似乎我的对象无法转换为泛型类型。虽然它实际上是基类。为什么这不起作用?这对我来说似乎很合乎逻辑。
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
{
}
答案 0 :(得分:3)
此处的问题是约束表明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();
的子类。
您无法将具有基类的运行时类型的实例转换为其子类之一,因为它错过了子类添加的所有信息。
示例:
Cat
您希望该代码有效吗?当然不是,因为Animal
也是Animal
,但Cat
不是d.Bar = 42;
。
如果您希望上述代码实际工作,请问自己在执行以下代码时应该发生什么:Animal
Bar
不包含{{1}}的定义。
你的代码中也发生了同样的事情 - 游戏中的泛型更加模糊不清。
答案 1 :(得分:2)
T
也可以是从A
派生的类,因此您无法将A
的实例作为T
类型的参数。类似于调用方法的方法,它使用int
和object
类型的参数。
答案 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);