不带“虚拟”的基本方法与带“虚拟”的基本方法和带“新”的派生方法?

时间:2019-07-07 16:10:09

标签: c#

我正在尝试了解new virtual的方法。

以下两种方式有什么区别?

  • 在没有virtual的基类中定义方法,并在子类中定义具有相同名称和签名的方法

  • 使用virtual在基类中定义一个方法,并在子类中定义一个具有相同名称和签名的方法new

如果它们不同,为什么在下面的示例中它们表现相同?

using System;

public class Base
{
    public void DoIt()
    {
      Console.WriteLine ("Base: DoIt");
    }

    public virtual void DoItVirtual1()
    {
      Console.WriteLine ("Base: DoItVirtual1");
    }

    public virtual void DoItVirtual2()
    {
      Console.WriteLine ("Base: DoItVirtual2");
    }    

}

public class Derived : Base
{
    public void DoIt()
    {
      Console.WriteLine ("Derived: DoIt");
    }
    public override void DoItVirtual1()
    {
      Console.WriteLine ("Derived: DoItVirtual1");
    }
    public new void DoItVirtual2()
    {
      Console.WriteLine ("Derived: DoItVirtual2");
    }        
}

class MainClass {
  public static void Main (string[] args) {
    Base b = new Base();
    Derived d = new Derived();
    Base bd = new Derived();

    b.DoIt(); 
    d.DoIt(); 
    bd.DoIt();

    b.DoItVirtual1();
    d.DoItVirtual1();
    bd.DoItVirtual1();

    b.DoItVirtual2();
    d.DoItVirtual2();
    bd.DoItVirtual2();
  }
}

输出:

Base: DoIt
Derived: DoIt
Base: DoIt
Base: DoItVirtual1
Derived: DoItVirtual1
Derived: DoItVirtual1
Base: DoItVirtual2
Derived: DoItVirtual2
Base: DoItVirtual2

3 个答案:

答案 0 :(得分:2)

public void configure() throws Exception { from("activemq:topic:saadtopic") .transform(simple(" ${body}")) .to("stream:out"); } 修饰符所产生的功能与您要删除它的功能相同,但是会禁止编译器发出有关无意中隐藏基类方法的警告。

  

使用new表示您知道该成员   修改后会隐藏从基类继承的成员。

new关键字与此处的virtual修饰符无关。它只允许您new派生类中的方法。

此处有更多信息:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords

答案 1 :(得分:0)

在派生类中使用“ new”关键字与不使用“ new”具有相同的效果,无论是否存在“虚拟”关键字。

“虚拟”与“替代”一起使用。

“新”仅在派生类上下文中单独起作用。

  

如果它们不同,为什么在下面的示例中它们表现相同?

查看输出的差异:

Base: DoItVirtual1
Derived: DoItVirtual1
Derived: DoItVirtual1

Base: DoItVirtual2
Derived: DoItVirtual2
Base: DoItVirtual2

在重写的虚拟方法中,强制转换回Base类的Derived实例的行为类似于Derived实例。这称为多态。 在第二个示例中,使用new关键字时,运行时无法将强制转换的实例与Derived类连接。

答案 2 :(得分:0)

虚拟成员允许派生类替代实现,而新成员是其他成员,这些成员将相同名称的成员隐藏在基类中。

class A
{
    public virtual int X() => 1;
}

class B : A
{
    public override int X() => 2;
}

class C : B
{
    public new virtual int X() => 3;
}

class D : C
{
    public sealed override int X() => 4;
}

测试

var d = new D();
var dd = d.X();        // 4
var dc = ((C)d).X();   // 4
var db = ((B)d).X();   // 2
var da = ((A)d).X();   // 2

var c = new C();
var cc = c.X();        // 3
var cb = ((B)c).X();   // 2
var ca = ((A)c).X();   // 2

var b = new B();
var bb = b.X();        // 2
var ba = ((A)b).X();   // 2

var a = new A();
var aa = a.X();        // 1