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

案例1:基类

public void DoIt();

案例1:继承类

public new void DoIt();

案例2:基类

public virtual void DoIt();

案例2:继承类

public override void DoIt();

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


当前回答

我也有同样的问题,真的很困惑, 您应该考虑重写和new关键字只适用于类型为基类的对象和派生类的值的对象。在这种情况下,只有你会看到override和new的效果: 如果你有类A和类B, B继承自类A,然后你像这样实例化一个对象:

A a = new B();

现在,调用方法将考虑它的状态。 Override:意味着它扩展了方法的函数,然后在派生类中使用该方法,而new告诉编译器将该方法隐藏在派生类中,而在基类中使用该方法。 下面是关于这个主题的一个很好的观点:

https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396

其他回答

如果派生类中使用了关键字重写,则其重写父方法。

如果派生类中使用了关键字new,则派生方法被父方法隐藏。

这些测试不会显示功能差异:

BaseClass bc = new BaseClass();

bc.DoIt();

DerivedClass dc = new DerivedClass();

dc.ShowIt();

在这个例子中,被调用的Doit就是您期望被调用的Doit。

为了看到区别,你必须这样做:

BaseClass obj = new DerivedClass();

obj.DoIt();

您将看到,如果您运行该测试,在情况1中(正如您定义的那样),调用BaseClass中的DoIt(),在情况2中(如您定义的那样),调用DerivedClass中的DoIt()。

我也有同样的问题,真的很困惑, 您应该考虑重写和new关键字只适用于类型为基类的对象和派生类的值的对象。在这种情况下,只有你会看到override和new的效果: 如果你有类A和类B, B继承自类A,然后你像这样实例化一个对象:

A a = new B();

现在,调用方法将考虑它的状态。 Override:意味着它扩展了方法的函数,然后在派生类中使用该方法,而new告诉编译器将该方法隐藏在派生类中,而在基类中使用该方法。 下面是关于这个主题的一个很好的观点:

https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396

其中,new是最令人困惑的。通过实验,new关键字就像给开发人员提供了一个选项,通过显式定义类型,用基类实现覆盖继承的类实现。这就像反过来思考一样。

在下例中,结果将返回"Derived result",直到类型显式定义为BaseClass test,才会返回"Base result"。

class Program
{
    static void Main(string[] args)
    {
        var test = new DerivedClass();
        var result = test.DoSomething();
    }
}

class BaseClass
{
    public virtual string DoSomething()
    {
        return "Base result";
    }
}

class DerivedClass : BaseClass
{
    public new string DoSomething()
    {
        return "Derived result";
    }
}

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

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。它们实际上是两个完全独立的方法,只是碰巧有相同的名称,而不是派生方法重写基方法。

来源:微软博客