什么是"public new virtual void Method()"是什么意思?

Lau*_*_Li 14 c#

何时使用新的虚拟关键词来装饰方法?感情是什么?就像定义一个接口一样,并添加一个类来继承接口.但是使用新的虚拟来实现接口方法.

 interface IPrinter
{
    void Print();
}

 public class PrinterOne : IPrinter
{
    public void Print() 
    {
        Console.WriteLine("PrinterOne.");
    }
}

public class PrinterTwo : PrinterOne
{
    public new virtual void Print()
    {
        Console.WriteLine("PrinterTwo.");
    }
}

public class PrinterThree : PrinterTwo
{
    public override void Print()
    {
        Console.WriteLine("PrinterThree.");
    }
}

public class PrinterFour : PrinterThree
{
    public override void Print()
    {
        Console.WriteLine("PrinterFour.");
    }
}

 static void Main(string[] args)
    {
        IPrinter iprinter = new PrinterFour();
        iprinter.Print();//the output is PrinterOne? why???
        Console.ReadLine();
    }
Run Code Online (Sandbox Code Playgroud)

SLa*_*aks 12

new并且virtual是两个(大多数)不相关的关键字.

new意味着它会影响基本方法.
virtual允许子类覆盖它.

通过接口调用该方法会导致调用基本方法,因为基本方法不是virtual,并且派生类不会显式重新实现接口(这会导致重新映射该方法)


Ada*_*rth 11

new像这样使用的关键字是成员隐藏.

我从未见过它与virtual关键字一起使用,请注意.它只是允许从派生类型PrinterTwooverridePrint方法实现.

new这种方式使用的关键字允许类型隐藏基类型的成员,但前提是您使用的是类型本身的变量.

例如,如果你这样做:

PrinterOne one = new PrinterTwo();
one.Print();
Run Code Online (Sandbox Code Playgroud)

不会调用该方法,PrinterTwo因为它不是继承链的一部分.

至于什么时候你会这样做...当你真的,真的需要一些奇怪的原因,我想不到(反射可能吗?),你不能编辑代码PrinterOne.

就个人而言,我不会这样做.

至于为什么输出是打印机的...调用IPrinter.Print将调用它所定义的类型(PrinterOne在这种情况下),这将使你回到上面关于new被忽略的关键字的示例,除非你谈到它的类型.

基本上,使用IPrinter类似于PrinterOne在上面的小例子中使用.

要解决问题,请制作PrinterOne方法virtual并完全删除使用new virtualPrinterTwo.


Ken*_*rey 5

新修饰符

http://msdn.microsoft.com/en-us/library/435f1dw2.aspx

当用作修饰符时,new关键字显式隐藏从基类继承的成员。

这意味着该方法不会覆盖虚拟基类方法,但是在派生类的实例上调用时,它仍然具有优先权。换句话说,新方法仅影响派生类的变量,而不影响基类。

虚拟修饰符

http://msdn.microsoft.com/zh-CN/library/9fkccyh4.aspx

virtual关键字用于修改方法,属性,索引器或事件声明,并允许其在派生类中被覆盖。

这意味着可以在派生类中重写该方法。当您在基类变量上调用虚拟方法时,该基类变量包含已覆盖该虚拟方法的派生类的实例,则将调用派生类实现。这与new关键字的行为相反。