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

案例1:基类

public void DoIt();

案例1:继承类

public new void DoIt();

案例2:基类

public virtual void DoIt();

案例2:继承类

public override void DoIt();

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


当前回答

在情况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的所有组合:

这两种情况的区别在于,在情况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。

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

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

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

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

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

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

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

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

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

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