4

我对 new 关键字有些困惑,当我使用 virtual 和 override 时一切正常,但与 new 有点不同(我想我遗漏了一些东西)

 class A
{
    public virtual void Test()
    {
        Console.WriteLine("I am in A");
    }
}

class B:A
{
    public override void Test()
    {
        Console.WriteLine("I am in B");
    }
}


class Program
{
    static void Main(string[] args)
    {
        B b = new B();
        b.Test(); //I am in B
        A a = new B();
        Console.WriteLine(a.GetType()); // Type-B
        a.Test(); //I am in B
       Console.ReadKey();
    }
}

}

现在有了新

class A
{
    public  void Test()
    {
        Console.WriteLine("I am in A");
    }
}

class B:A
{
    public new void Test()
    {
        Console.WriteLine("I am in B");
    }
}


class Program
{
    static void Main(string[] args)
    {
        B b = new B();
        b.Test(); //I am in B
        A a = new B();
        Console.WriteLine(a.GetType()); //B
        a.Test(); // I am in A ? why?
       Console.ReadKey();
    }
}

根据 MSDN,当使用 new 关键字时,会调用新的类成员,而不是已替换的基类成员。那些基类成员称为隐藏成员,GetType() 也将类型显示为 B。所以我哪里出错了,这似乎是一个愚蠢的错误 :-)

4

4 回答 4

2

查看Jon Skeetnew关键字用法的描述。因为 a 被强制转换为 A,所以您正在调用 A 的方法,该方法不能被覆盖。B 恰好有一个同名的方法。

于 2010-02-22T18:21:51.303 回答
2

当您使用关键字隐藏基类方法new时,调用由编译器解析,而不是在运行时解析。

因此,当您编写 时a.Test,编译器会发出Test对类上的方法的调用A。即使a变量碰巧引用了一个B实例,编译器也不在乎,它仍然调用A.

当您调用虚拟方法时,编译器会发出一条callvirt指令,告诉运行时根据实例的实际类型找到要调用的正确方法。运行时知道实例实际上是 type B,并且会看到它B覆盖了方法并调用覆盖的版本。

于 2010-02-22T18:23:23.003 回答
0

基本上,一旦您创建了派生自Aor的其他类B,您会发现调用base.Test()将调用A's 版本的那些类,override而不是new那些派生自B将具有B' 版本称为但 NOTA的类。

于 2010-02-22T18:23:58.507 回答
0

“新”意味着该方法是“新的”而不是“覆盖”。因此,如果您从基类调用该名称的方法,它尚未被覆盖,因此不会调用派生类。

于 2018-10-26T14:55:00.103 回答