在以下情况下多态性似乎无法正常工作 我有以下定义:
interface BaseInterface{}
interface NewInterface:BaseInterface{}
class NewClass:NewInterface{}
class GenericClass<T> where T:BaseInterface
{
public string WhoIAm(T anObject)
{
return TestPolymorphism.CheckInterface(anObject);
}
}
class ImplementedClass:GenericClass<NewInterface>{}
class TestPolymorphism
{
public static string CheckInterface(BaseInterface anInterface)
{
return "BaseInterface";
}
public static string CheckInterface(NewInterface anInterface)
{
return "NewInterface";
}
}
然后当我打电话时:
NewClass nc = new NewClass();
ImplementedClass impClass = new ImplementedClass();
Console.WriteLine("The result is " + impClass.WhoIAm(nc));
我有“结果是 BaseInterface”
当 nc 实现 BaseClass 和 NewClass
时,我期待“结果是 NewInterface”
获得“NewClass”结果的最佳方式是什么?
谢谢
最佳答案
请记住泛型方法,非虚拟方法调用仍然在泛型本身的编译时解析,不是在泛型实现的编译时解析。
因此:
class GenericClass<T> where T:BaseInterface
{
public string WhoIAm(T anObject)
{
return TestPolymorphism.CheckInterface(anObject);
}
}
将解析为需要 BaseInterface
的重载因为无论类型 T
是什么,您都将其限制为实际上是。
C# 中的泛型与 C++ 中的模板不太一样,在 C# 泛型中,所有引用类型都共享相同的泛型代码,因此它们在编译时都以相似的方式对待泛型类型。这意味着任何编译时重载您使用泛型类型占位符的泛型调用只能通过您对泛型类型本身提供的任何约束,因为泛型在实际实现之前就已编译。
也就是你的GenericClass<T>
在考虑使用它之前进行编译(这与 C++ 处理模板的方式非常不同——这两种方法各有利弊)。所以,如果你有一个不受约束的泛型(比如,只是 T
)那么它被认为是 object
出于重载的目的(粗略地说),但如果你有一个受约束的泛型(比如 where T : BaseInterface
)那么它被认为是 BaseInterface
用于重载。
在这种情况下你会看到类似的东西:
public static bool UberEquals<T>(T left, T right) where T : class
{
return left == right;
}
所以你会想,如果你通过以下方式调用它:
var s1 = "ello";
var s2 = "Hello";
UberEquals<string>('H' + s1, s2);
自 T
类型是 string
然后它会调用string
s ==
过载,但它没有,因为你没有约束 T
, 因此在编译时它假定最小公分母为 object
并使用 object
s ==
相反。
另一种思考方式:
BaseInterface bi = new ImplementedClass();
var x = TestPolymorphism.CheckInterface(bi);
X 总是说 BaseInterface
在上面,因为重载是在编译时解决的,而不是在运行时动态解决的。与泛型非常相似,请记住,泛型是在实现之前编译的,因此它只能在您出于重载决议的目的而将其约束到的任何基类或接口(interface)上运行。
关于c# - 多态性不适用于 C# 中泛型类的调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10823208/