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

案例1:基类

public void DoIt();

案例1:继承类

public new void DoIt();

案例2:基类

public virtual void DoIt();

案例2:继承类

public override void DoIt();

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


当前回答

请尝试以下操作:(case1)

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

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

其他回答

其中,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";
    }
}

new:它只是隐藏基类的方法,但如果你想要访问它。

override:它覆盖了基类的方法,即使你想访问它也无法访问。

例子

using System;

public class Program
{
    public static void Main()
    {
        BaseClass test = new DerivedClass();
        var result = test.DoSomething();
        
        Console.WriteLine(result);
    }

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

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

结果:基础结果

附注:我从下面的链接复制并稍微改变了上面的例子: https://stackoverflow.com/a/45822233/10995103

Virtual:表示该方法可以被继承者覆盖

Override:覆盖基类中虚方法的功能,提供不同的功能。

New:隐藏原来的方法(不一定是虚拟的),提供不同的功能。这应该只在绝对必要的情况下使用。

当您隐藏一个方法时,您仍然可以通过向上强制转换为基类来访问原始方法。这在某些情况下很有用,但也很危险。

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

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

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