想知道以下两者之间的区别:
案例1:基类
public void DoIt();
案例1:继承类
public new void DoIt();
案例2:基类
public virtual void DoIt();
案例2:继承类
public override void DoIt();
根据我运行的测试,情况1和2似乎具有相同的效果。有区别吗,或者有更好的方式吗?
想知道以下两者之间的区别:
案例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只是创建同名的新方法,并隐藏旧方法,它在编译时被解析->你的编译器将调用它'看到'的方法
其他回答
在情况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();
}
重写修饰符可以用于 虚方法和必须在上使用 抽象方法。这表明 编译器使用最后定义的 方法的实现。即使 的引用调用该方法 类的基类 实现重写它。
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。它们实际上是两个完全独立的方法,只是碰巧有相同的名称,而不是派生方法重写基方法。
来源:微软博客
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
在第一种情况下,您将定义隐藏在父类中。这意味着只有在将对象作为子类处理时才会调用它。如果将类强制转换为其父类型,则将调用父类的方法。在第二个实例中,该方法将被重写,并将被调用,而不管对象是转换为子类还是父类。
这两种情况的区别在于,在情况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。