Welcome

首页 / 软件开发 / .NET编程技术 / 解析.net中继承的实质

解析.net中继承的实质2011-03-31 csdn博客 傅晗在csdn论坛、博客园里都有很多帖子讨论c#中继承语法的问题,大家乐此不疲的解释 virtual,override,new,final,接口,类中的继承。各种各样的例子让新手头晕脑胀 ,这其中还一些地方以讹传讹。

比如这篇文章里面竟然说“编译器会顺着继承链往下找,一直找到合适的那个方法体 ”,在回复里还有人说“这个特征特现了C#编译器对里氏代换原则的支持。也就是:凡是 基类适用的地方子类一定适用。

比如class Base {},class Sub:base {} 如果:Base a=new Sub();那么实际上编译 器已经能够确定a所指向的对象的类型。所以方法的地址确实是在编译期就确定了的。” 。我真是无语了,override的实现本质上是非常简单的,但由于每次都是从语法的角度讨 论问题所以总是不得要领。

所以我这篇帖子的将从底层实现的角度来向你说明override的实现。首先让我们明确2 个概念:

1.类实例的方法调用都是虚调用(callvirt)只有在调用基类方法时是实调用(call )。请看代码:

1. class A
2. {
3. public void Boo()
4. {
5. Console.WriteLine("A::Boo().");
6. }
7. public virtual void Foo()
8. {
9. Console.WriteLine("A::Foo().");
10. }
11. }
12. class B : A
13. {
14. public override void Foo()
15. {
16. Console.WriteLine("B::Foo().");
17. base.Foo();
18. }
19. }
20. class Class1
21. {
22. public static void Main()
23. {
24. A a = new A();
25. a.Foo();
26. a.Boo();
27. A b = new B();
28. a.Foo();
29. a.Boo();
30. }
31. }

让我看一下对应的IL代码片段

1. //main函数,调用实例函数的IL
2. //a.Foo();
3. IL_0007: callvirt instance void test_console.A::Foo()
4. //a.Boo();
5. IL_000d: callvirt instance void test_console.A::Boo()
6. //b.Foo();
7. IL_0019: callvirt instance void test_console.A::Foo()
8. //b.Boo ();
9. IL_001f: callvirt instance void test_console.A::Boo()
10.
11. //B类中Foo函数
12. IL_0000: ldstr "B::Foo()."
13. IL_0005: call void [mscorlib]System.Console::WriteLine(string)
14. IL_000a: ldarg.0
15. //base.Foo();
16. IL_000b: call instance void test_console.A::Foo()
17. IL_0010: ret