c# - 多态性不适用于 C# 中泛型类的调用

标签 c# class generics interface polymorphism

在以下情况下多态性似乎无法正常工作 我有以下定义:

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/

相关文章:

ios - 在与非泛型父类(super class)同名的泛型类中使用类方法时出错

C# - 从现有进程中读取文本

c# - 使用 Linq + group by 查询容器?

c# - 读一个文件,谁的行改变类型

python - 类属性评估和生成器

java - 如果只在对象初始化时分配内存,类成员变量(实例变量)如何初始化?

java - 方法类型参数仅在签名中使用一次 - 有道理吗?

c# - 如何在 C# 中克隆通用列表?

c# - OnClientClick 阻止 OnClick 事件?

c# - 在 LINQ 中,如何为每个 ID 选择一项?