[Programming IL]虚方法,重载,抽象方法,覆盖 - Virtual Methods, Overload, Abstract, Override
引言
前面我们讲到了接口,类,流程控制,那面向对象的一些基本概念,重载,覆盖,抽象/虚方法这些概念在.Net中又是如何实现的呢?
概念
可能提了无数次了,然后还是要定义一下, 温故而知新嘛. :) 这些面向对象的基本元素都是和方法联系在一起。方法由方法头(Method Header)和方法体(Method Body)组成,方法头由 ( 修饰符,返回值,方法名,定义域修饰符(internal), 参数列表,方法Attribute )组成. 而方法体里的内容比较复杂
方法项 | 描述 |
.custom CustomDecl | 定义自定义标签(Attributes) |
.data DataDecl | 将数据存在在PE中 |
.emitbyte Int32 | 将一个8位的Unsigned byte生成到方法的.code段中,该标志只适用于生成测试,并不会在常规程序中出现 |
.entrypoint | 在前面已经有提及,标志方法为入口点 |
.locals [ init ] method. |
初始化方法中的一些字段. 例子: .locals init ( int32 i, int32 j, float32 f, int64[] vect) |
.maxstack Int32 | 定义在执行栈上最多存放多少个元素 |
.override TypeSpec:: MethodName .override method CallConv Type TypeSpec::!MethodName GenArity (with method CallConv Type TypeSpec::!MethodName GenArity |
为子类的虚方法或者接口方法提供具体实现. 在编译成PE则会存放在MethodImpl表中. 例子: .class interface I |
.param [Int32] [=FieldInit] | Int32代表参数索引,注意: 0 代表返回类型 |
.param type [ Int32 ] | 泛型参数,当位于泛型类中,由类中的泛型类型来确定类型。 Sample: .class public G<T,U> { |
ExternSourceDecl | .line 指向代码中的其他行 |
Instr | 一个对String进行操作的指令 |
Id : | 标签Label |
ScopeBlock | 代码段 |
SecurityDecl | .permission or .permissionset, 权限验证 |
SEHBlock | SEH = 结构化异常处理,异常处理块 |
这里提到了override, 那么abstract 和 virtual 呢? 这里这些指令要放在一起. 我们从一个例子开始吧
从例子开始
代码:
1: using System;
2: public class Testing
3: {
4: public static void Main()
5: {
6: // Use The Bae Type To Call The Methods
7: MyBase base1 = new MyChild();
8: base1.BaseFunction();
9: base1.BaseFun2();
10:
11: // Use The Child Type to call the methods
12: MyChild child = new MyChild();
13: child.BaseFun2();
14: child.Fun();
15: child.Fun("XWang");
16:
17: // Abstract - Override Implemention
18: MyAbstractBase base2 = new MyConcerateClass();
19: base2.MyAbastractFun();
20:
21: Console.ReadKey();
22: }
23: }
24:
25: public class MyBase
26: {
27: public virtual void BaseFunction()
28: {
29: Console.WriteLine("This is the BaseFunction In MyBase");
30: }
31:
32: public virtual void BaseFun2()
33: {
34: Console.WriteLine("This is the BaseFun2 In MyBase");
35: }
36: }
37:
38: public class MyChild : MyBase
39: {
40: // Virual - Override
41: public override void BaseFunction()
42: {
43: Console.WriteLine("This is the BaseFunction in MyChild");
44: }
45:
46: // NewsLot Method
47: public new void BaseFun2()
48: {
49: Console.WriteLine("This is the new BaseFun2 in MyChild");
50: }
51:
52: // OverLoad
53: public void Fun()
54: {
55: Console.WriteLine("This is the Fun In MyChild");
56: }
57:
58: public void Fun(string name)
59: {
60: Console.WriteLine("This is the Fun(string name) in MyChild. Hello: {0}", name);
61: }
62: }
63:
64: public abstract class MyAbstractBase
65: {
66: public abstract void MyAbastractFun();
67: }
68:
69: public class MyConcerateClass : MyAbstractBase
70: {
71: // Abstarct - Override
72: public override void MyAbastractFun()
73: {
74: Console.WriteLine("This is implemention of MyAbastractFun in MyChild");
75: }
76:
77: }
看看结果:
好像有点乱,我们做个表对应分析一下
方法 | 执行结果 |
base1.BaseFunction(); | This is the BaseFunction in MyChild |
base1.BaseFun2(); | This is the BaseFun2 In MyBase |
child.BaseFun2(); | This is the new BaseFun2 in MyChild |
child.Fun(); | This is the Fun In MyChild |
child.Fun("XWang"); | This is the Fun(string name) in MyChild. Hello: XWang |
base2.MyAbastractFun(); | This is implemention of MyAbastractFun in MyChild |
规律:
1. Virtual 和 Abstract和Override之后都会执行子类的实现
2. 当有new做标记时,不会跳转到子类的实现,两个类相对独立
亲爱的读者,你想不想探索一下呢?Follow me:
反编译
代码太长, 觉得麻烦下面抽重点分析
1: .class public auto ansi beforefieldinit MyBase
2: extends [mscorlib]System.Object
3: {
4: .method public hidebysig newslot virtual
5: instance void BaseFunction() cil managed
6: {
7: // Code size 11 (0xb)
8: .maxstack 8
9: IL_0000: ldstr "This is the BaseFunction In MyBase"
10: IL_0005: call void [mscorlib]System.Console::WriteLine(string)
11: IL_000a: ret
12: } // end of method MyBase::BaseFunction
13:
14: .method public hidebysig newslot virtual
15: instance void BaseFun2() cil managed
16: {
17: // Code size 11 (0xb)
18: .maxstack 8
19: IL_0000: ldstr "This is the BaseFun2 In MyBase"
20: IL_0005: call void [mscorlib]System.Console::WriteLine(string)
21: IL_000a: ret
22: } // end of method MyBase::BaseFun2
23:
24: .method public hidebysig specialname rtspecialname
25: instance void .ctor() cil managed
26: {
27: // Code size 7 (0x7)
28: .maxstack 8
29: IL_0000: ldarg.0
30: IL_0001: call instance void [mscorlib]System.Object::.ctor()
31: IL_0006: ret
32: } // end of method MyBase::.ctor
33:
34: } // end of class MyBase
35:
36: .class public auto ansi beforefieldinit MyChild
37: extends MyBase
38: {
39: .method public hidebysig virtual instance void
40: BaseFunction() cil managed
41: {
42: // Code size 11 (0xb)
43: .maxstack 8
44: IL_0000: ldstr "This is the BaseFunction in MyChild"
45: IL_0005: call void [mscorlib]System.Console::WriteLine(string)
46: IL_000a: ret
47: } // end of method MyChild::BaseFunction
48:
49: .method public hidebysig instance void
50: BaseFun2() cil managed
51: {
52: // Code size 11 (0xb)
53: .maxstack 8
54: IL_0000: ldstr "This is the new BaseFun2 in MyChild"
55: IL_0005: call void [mscorlib]System.Console::WriteLine(string)
56: IL_000a: ret
57: } // end of method MyChild::BaseFun2
58:
59: .method public hidebysig instance void
60: Fun() cil managed
61: {
62: // Code size 11 (0xb)
63: .maxstack 8
64: IL_0000: ldstr "This is the Fun In MyChild"
65: IL_0005: call void [mscorlib]System.Console::WriteLine(string)
66: IL_000a: ret
67: } // end of method MyChild::Fun
68:
69: .method public hidebysig instance void
70: Fun(string name) cil managed
71: {
72: // Code size 12 (0xc)
73: .maxstack 8
74: IL_0000: ldstr "This is the Fun(string name) in MyChild. Hello: {0}"
75: IL_0005: ldarg.1
76: IL_0006: call void [mscorlib]System.Console::WriteLine(string,
77: object)
78: IL_000b: ret
79: } // end of method MyChild::Fun
80:
81: .method public hidebysig specialname rtspecialname
82: instance void .ctor() cil managed
83: {
84: // Code size 7 (0x7)
85: .maxstack 8
86: IL_0000: ldarg.0
87: IL_0001: call instance void MyBase::.ctor()
88: IL_0006: ret
89: } // end of method MyChild::.ctor
90:
91: } // end of class MyChild
92:
93: .class public abstract auto ansi beforefieldinit MyAbstractBase
94: extends [mscorlib]System.Object
95: {
96: .method public hidebysig newslot abstract virtual
97: instance void MyAbastractFun() cil managed
98: {
99: } // end of method MyAbstractBase::MyAbastractFun
100:
101: .method family hidebysig specialname rtspecialname
102: instance void .ctor() cil managed
103: {
104: // Code size 7 (0x7)
105: .maxstack 8
106: IL_0000: ldarg.0
107: IL_0001: call instance void [mscorlib]System.Object::.ctor()
108: IL_0006: ret
109: } // end of method MyAbstractBase::.ctor
110:
111: } // end of class MyAbstractBase
112:
113: .class public auto ansi beforefieldinit MyConcerateClass
114: extends MyAbstractBase
115: {
116: .method public hidebysig virtual instance void
117: MyAbastractFun() cil managed
118: {
119: // Code size 11 (0xb)
120: .maxstack 8
121: IL_0000: ldstr "This is implemention of MyAbastractFun in MyChild"
122: IL_0005: call void [mscorlib]System.Console::WriteLine(string)
123: IL_000a: ret
124: } // end of method MyConcerateClass::MyAbastractFun
125:
126: .method public hidebysig specialname rtspecialname
127: instance void .ctor() cil managed
128: {
129: // Code size 7 (0x7)
130: .maxstack 8
131: IL_0000: ldarg.0
132: IL_0001: call instance void MyAbstractBase::.ctor()
133: IL_0006: ret
134: } // end of method MyConcerateClass::.ctor
135:
136: } // end of class MyConcerateClass
对应的IL解释
方法 | ILAsm |
base1.BaseFunction(); |
[MyBase]: .method public hidebysig newslot virtual instance void BaseFunction() cil managed [MyChild]: .method public hidebysig virtual instance void BaseFunction() cil managed |
base1.BaseFun2(); |
[MyBase/MyChild].method public hidebysig newslot virtual instance void BaseFun2() cil managed |
child.BaseFun2(); | [MyChild]: .method public hidebysig instance void BaseFun2() cil managed |
child.Fun(); | [MyChild]: .method public hidebysig instance void Fun() cil managed |
child.Fun("XWang"); | [MyChild]: .method public hidebysig instance void Fun(string name) cil managed |
base2.MyAbastractFun(); | [MyChild] .method public hidebysig virtual instance void MyAbastractFun() cil managed
[MyBase] .method public hidebysig newslot abstract virtual instance void MyAbastractFun() cil managed |
可以看到父类的Virtual和子类的实现差别在于 newslot virtual,我们看看对于这个指令的解释
If the class defines any public virtual newslot methods whose name and
signature match a virtual method on the interface, then use these new virtual methods
to implement the corresponding interface method.当在方法前定义newslot virtual则当他们实现中碰到同样签名的方法时则立即执行跳转,关于内存结构的部分,之前有讲到, 指令上则是call 和 callvirt 的差别
到这里我想该有的基础都有了,那么正式开始我们的IL 程序吧. :)
代码如下:
1: .assembly extern mscorlib {}
2: .assembly OOPSample {}
3: .module OOP.exe
4: .class public auto ansi Testing extends [mscorlib]System.Object
5: {
6: .method public static void Main() cil managed
7: {
8: .entrypoint
9: .maxstack 2
10: .locals init (class MyBase V_0)
11: newobj instance void MyChild::.ctor()
12: stloc.0
13: ldloc.0
14: callvirt instance void MyBase::MyBaseFun()
15:
16: ret
17: }
18: }
19:
20: // define the base class
21: .class public auto MyBase extends [mscorlib]System.Object
22: {
23: .method public newslot virtual instance void MyBaseFun() cil managed
24: {
25: .maxstack 8
26: ldstr "This is the MyBaseFun In MyBase"
27: call void [mscorlib]System.Console::WriteLine(string)
28: ret
29: }
30:
31: .method public specialname rtspecialname instance void .ctor() cil
32:
33: managed
34: {
35: .maxstack 8
36: ldarg.0
37: call instance void [mscorlib]System.Object::.ctor()
38: ret
39: }
40: }
41:
42: // Define the Concerate Implemention
43: .class public auto MyChild extends MyBase
44: {
45: .method public virtual instance void MyBaseFun() cil managed
46: {
47: .maxstack 8
48: ldstr "This is the MyBaseFun In MyChild"
49: call void [mscorlib]System.Console::WriteLine(string)
50: ret
51: }
52:
53: .method public specialname rtspecialname instance void .ctor() cil
54:
55: managed
56: {
57: .maxstack 8
58: ldarg.0
59: call instance void MyBase::.ctor()
60: ret
61: }
62: }
结果:
结合本文开头介绍的方法理解这个应该不难,BTW: 这里还有最简单的Hello World版本哦