想知道以下两者之间的区别:

案例1:基类

public void DoIt();

案例1:继承类

public new void DoIt();

案例2:基类

public virtual void DoIt();

案例2:继承类

public override void DoIt();

根据我运行的测试,情况1和2似乎具有相同的效果。有区别吗,或者有更好的方式吗?


当前回答

重写修饰符可以用于 虚方法和必须在上使用 抽象方法。这表明 编译器使用最后定义的 方法的实现。即使 的引用调用该方法 类的基类 实现重写它。

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public override void DoIt()
    {
    }
}

Base b = new Derived();
b.DoIt();                      // Calls Derived.DoIt

将调用Derived。如果它覆盖base,就做。

新的修饰符指示 编译器来使用您的子类实现 而不是父类 实现。任何不是这样的代码 引用你的类而不是父类 类将使用父类 实现。

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public new void DoIt()
    {
    }
}

Base b = new Derived();
Derived d = new Derived();

b.DoIt();                      // Calls Base.DoIt
d.DoIt();                      // Calls Derived.DoIt

会先打电话给基地。DoIt,然后是derived。DoIt。它们实际上是两个完全独立的方法,只是碰巧有相同的名称,而不是派生方法重写基方法。

来源:微软博客

其他回答

在情况1中,如果您使用调用继承类的DoIt()方法,而类型被声明为基类,您甚至可以看到基类的操作。

/* Results
Class1
Base1
Class2
Class2
*/
public abstract class Base1
{
    public void DoIt() { Console.WriteLine("Base1"); }
}
public  class Class1 : Base1 
{
    public new void DoIt() { Console.WriteLine("Class1"); }
}
public abstract class Base2
{
    public virtual void DoIt() { Console.WriteLine("Base2"); }
}
public class Class2 : Base2
{
    public override void DoIt() { Console.WriteLine("Class2"); }
}
static void Main(string[] args)
{
    var c1 = new Class1();
    c1.DoIt();
    ((Base1)c1).DoIt();

    var c2 = new Class2();
    c2.DoIt();
    ((Base2)c2).DoIt();
    Console.Read();
}

在第一种情况下,您将定义隐藏在父类中。这意味着只有在将对象作为子类处理时才会调用它。如果将类强制转换为其父类型,则将调用父类的方法。在第二个实例中,该方法将被重写,并将被调用,而不管对象是转换为子类还是父类。

none、virtual、override、new和abstract的所有组合:

new means respect your REFERENCE type(left-hand side of =) , thereby running reference types's method. If redefined method doesn't have new keyword, it is behaved as it has. Moreover, it also known as non-polymorphic inheritance. That is, “I’m making a brand new method in the derived class that has absolutely nothing to do with any methods by the same name in the base class.” - by said Whitaker override, which must be used with virtual keyword in its base class, means respect your OBJECT type(right-hand side of =), thereby running method overriden in regardless of reference type. Moreover, it also known as polymorphic inheritance.


我的方法是记住这两个关键字,它们是彼此相反的。

Override:必须定义virtual关键字来覆盖该方法。使用override关键字的方法,无论引用类型(基类或派生类的引用),如果它是用基类实例化的,基类的方法都会运行。否则,派生类的方法运行。

新:如果关键字被一个方法使用,与override关键字不同,引用类型很重要。如果它是用派生类实例化的,并且引用类型是基类,则运行基类的方法。如果它是用派生类实例化的,并且引用类型是派生类,则运行派生类的方法。即override关键字的对比。顺便说一下,如果你忘记或忽略向方法添加new关键字,编译器默认行为为使用new关键字。

class A 
{
    public string Foo() 
    {
        return "A";
    }

    public virtual string Test()
    {
        return "base test";
    }
}

class B: A
{
    public new string Foo() 
    {
        return "B";
    }
}

class C: B 
{
    public string Foo() 
    {
        return "C";
    }

    public override string Test() {
        return "derived test";
    }
}

主呼叫:

A AClass = new B();
Console.WriteLine(AClass.Foo());
B BClass = new B();
Console.WriteLine(BClass.Foo());
B BClassWithC = new C();
Console.WriteLine(BClassWithC.Foo());

Console.WriteLine(AClass.Test());
Console.WriteLine(BClassWithC.Test());

输出:

A
B
B
base test
derived test

新代码示例,

通过逐个注释来处理代码。

class X
{
    protected internal /*virtual*/ void Method()
    {
        WriteLine("X");
    }
}
class Y : X
{
    protected internal /*override*/ void Method()
    {
        base.Method();
        WriteLine("Y");
    }
}
class Z : Y
{
    protected internal /*override*/ void Method()
    {
        base.Method();
        WriteLine("Z");
    }
}

class Programxyz
{
    private static void Main(string[] args)
    {
        X v = new Z();
        //Y v = new Z();
        //Z v = new Z();
        v.Method();
}

下面的文章是在vb.net,但我认为关于新的vs重写的解释是很容易理解的。

https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides

在文章的某个地方,出现了这样一句话:

通常,Shadows假定与类型相关联的函数为 调用,而override假设对象实现为 执行。

这个问题的公认答案是完美的,但我认为这篇文章提供了很好的例子来更好地解释这两个关键字之间的差异。