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

案例1:基类

public void DoIt();

案例1:继承类

public new void DoIt();

案例2:基类

public virtual void DoIt();

案例2:继承类

public override void DoIt();

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


当前回答

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

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()。

其他回答

这两种情况的区别在于,在情况1中,基本DoIt方法不会被覆盖,只是被隐藏。这意味着变量的类型取决于调用哪个方法。例如:

BaseClass instance1 = new SubClass();
instance1.DoIt(); // Calls base class DoIt method

SubClass instance2 = new SubClass();
instance2.DoIt(); // Calls sub class DoIt method

这确实会令人困惑,并导致非预期的行为,如果可能的话应该避免。所以首选的方法是情形2。

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();
}

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

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

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()。

请尝试以下操作:(case1)

((BaseClass)(new InheritedClass())).DoIt()

编辑:virtual+override在运行时被解析(因此override真正覆盖虚拟方法),而new只是创建同名的新方法,并隐藏旧方法,它在编译时被解析->你的编译器将调用它'看到'的方法