new & override 不完全PK
从一段简单的代码开始:
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class A
{
public virtual void Call()
{ Console.WriteLine("this is class A"); }
}
class B : A
{
public new void Call()
{ Console.WriteLine("this is class B"); }
}
class C : A
{
public override void Call()
{ Console.WriteLine("this is class C"); }
public void Call2()
{ Console.WriteLine("this is class C"); }
}
class Program
{
static void Main(string[] args)
{
//情况1
A a1 = new B();
A a2 = new C();
a1.Call();
a2.Call();
//情况2
B a3 = new B();
a3.Call();
//情况3
C a4 = new C();
a4.Call();
a4.Call2();
Console.ReadLine();
}
}
}
试问这点代码的执行结果是什么?
Why?从IL来看:
{
.entrypoint
// 代码大小 & nbsp; 67 (0x43)
.maxstack 1
.locals init ([0] class ConsoleApplication1.A a1,
[1] class ConsoleApplication1.A a2,
[2] class ConsoleApplication1.B a3,
[3] class ConsoleApplication1.C a4)
IL_0000: nop
IL_0001: newobj instance void ConsoleApplication1.B::.ctor()
IL_0006: stloc.0
IL_0007: newobj instance void ConsoleApplication1.C::.ctor()
IL_000c: stloc.1
IL_000d: ldloc.0
IL_000e: callvirt instance void ConsoleApplication1.A::Call()
IL_0013: nop
IL_0014: ldloc.1
IL_0015: callvirt instance void ConsoleApplication1.A::Call()
IL_001a: nop
IL_001b: newobj instance void ConsoleApplication1.B::.ctor()
IL_0020: stloc.2
IL_0021: ldloc.2
IL_0022: callvirt instance void ConsoleApplication1.B::Call()
IL_0027: nop
IL_0028: newobj instance void ConsoleApplication1.C::.ctor()
IL_002d: stloc.3
IL_002e: ldloc.3
IL_002f: callvirt instance void ConsoleApplication1.A::Call()
IL_0034: nop
IL_0035: ldloc.3
IL_0036: callvirt instance void ConsoleApplication1.C::Call2()
IL_003b: nop
IL_003c: call string [mscorlib]System.Console::ReadLine()
IL_0041: pop
IL_0042: ret
} // end of method Program::Main
不完全结论是:
情况1时,a1.Call()和a2.Call()的IL代码都是callvirt instance void ConsoleApplication1.A::Call(),但是不同的是,a1.Call()结果是this is class A而a2.Call()结果是this is class C,为什么呢?因为B类里是public new void Call(),而C类里是public override void Call();
情况2,没什么可说的,貌似一切正常!
情况3,有点意思了,a4.Call() 对应得IL是callvirt instance void ConsoleApplication1.A::Call(),而结果却是this is class C,为什么呢?a4.Call2()也是貌似一切正常。
综合上面的几种情况,我们可以得出如下结论,从情况2和 a4.Call2()表现一致来看,使用new的作用跟完全重新声明一个新方法没什么区别;从情况1里的a2.Call()和情况3里的a4.Call()表现一致来看,a.生成IL代码的时候,如果调用的方法在父类里存在,且在子类里覆盖了这个方法,那么不管声明的引用变量是父类(情况1)还是子类(情况3),生成的IL代码都是调用父类的方法(callvirt instance void ConsoleApplication1.A::Call());b.运行时CLR执行顺序是从父类到子类(从上到下),如果父类的方法是虚方法,则去子类里找是否有子类覆盖了这个方法,没有则还是执行父类里的方法,如果有就执行子类里的方法;
以上这些只是即兴做了一个简单对比,只是推测不是标准答案,而且应该很不完全,欢迎大家补充。
---------------------------------------------------------------------------------------
![](https://www.cnblogs.com/Emoticons/tusiji/203707182.gif)
请大家参考3楼精彩的文章:http://blog.csdn.net/fuadam/archive/2008/08/25/2827561.aspx
出处:http://justinw.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。