C#泛型类型干扰奇怪的行为

Ben*_*nny 0 c# generics polymorphism

请考虑以下代码:

class Program
{
    static void Main(string[] args)
    {
        var a = new A();
        var b = new B();
        Print(a);
        Print(b);
        Console.WriteLine(b.Hello);
        Console.ReadLine();
    }

    static void Print<T>(T t) where T : A
    {
        Console.WriteLine(typeof(T));
        Console.WriteLine(t.GetType());
        Console.WriteLine(t.Hello);
    }
}

public class A
{
    public string Hello { get { return "HelloA"; } }
}

public class B : A
{
    public new string Hello { get { return "HelloB"; } }
}
Run Code Online (Sandbox Code Playgroud)

我得到的输出(.NET FW 4.5)

  • //打印(a)中
  • 一个
  • 一个
  • HelloA
  • //打印(b)中
  • HelloA
  • //明确的书写线
  • 你好乙

任何人都可以解释我是如何获得第二个HelloA的,因为我期待HelloB?

Hei*_*nzi 5

public new string Hello { get { return "HelloB"; } }
Run Code Online (Sandbox Code Playgroud)

new关键字创建一个函数,该函数恰好与函数同名.因此,B现在有两种方法:Hello(A),当通过编译时类型的变量调用时执行A,和Hello(B),当通过编译时类型的变量B(或其子类型)调用时执行.

由于您的泛型参数是T : A,编译器编译t.Hello为对Hello(A)的调用.

B 阴影(或隐藏)方法Hello而不是覆盖它.

你可能想写的是:

public class A
{
    public virtual string Hello { get { return "HelloA"; } }
}

public class B : A
{
    public override string Hello { get { return "HelloB"; } }
}
Run Code Online (Sandbox Code Playgroud)

请注意,base方法声明为virtual,而子类方法声明为override.

  • @Benny:泛型不是*运行时方法绑定.您只能访问在编译时可以验证其存在的方法:您*需要*`T:A`才能调用`t.Hello`.你*不能*调用`t.SomeMethodOnlyDefinedOnB`,它(基本上)是`Hello`(B).C#允许您重用名称的事实只是语法糖.您可以将阴影视为一些编译器魔术,它允许您编写`Hello`,您实际上需要编写`SomeMethodWithAnotherNameThanHello`. (2认同)