《CLR Via C# 第3版》笔记之(六) - IL中的call和callvirt

简介:

C#中调用一个函数时生成的IL代码有两种形式,分别为call 和 callvirt。

主要内容

  • call和callvirt的区别
  • call和callvirt的例子

1. call和callvirt的区别

call的callvirt的区别主要有两点:

1)call可以调用静态方法,实例方法和虚方法

     callvirt只能调用实例方法和虚方法,不能调用静态方法

2)call一般是以非虚的方式来调用函数的

     callvirt是以已多态的方式来调用函数的

2. call和callvirt的例子

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using  System;
 
namespace  Test6
{
     public  class  CLRviaCSharp_6
     {
         static  void  Main( string [] args)
         {
             BaseClass.SShow();
 
             BaseClass b = new  BaseClass();
             BaseClass s = new  SubClass();
             b.VShow();
             s.VShow();
             Console.ReadKey( true );
         }
     }
 
     public  class  BaseClass
     {
         public  static  void  SShow()
         {
             Console.WriteLine( "Base class static method: SShow()!" );
         }
 
         public  virtual  void  VShow()
         {
             Console.WriteLine( "Base class virtual method: VShow()!" );
         }
     }
 
     public  class  SubClass : BaseClass
     {
         public  override  void  VShow()
         {
             Console.WriteLine( "Sub class virtual method: VShow()!" );
         }       
     }
}

程序执行结果为:

image

利用ildasm.exe将上面代码生成的exe文件反编译为IL代码。

命令:ildasm .\Test6.exe /output:Test6.il

IL代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//  Microsoft (R) .NET Framework IL Disassembler.  Version 3.5.30729.1
//  Copyright (c) Microsoft Corporation.  All rights reserved.
 
 
 
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
   .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
   .ver 4:0:0:0
}
.assembly Test6
{
   .custom instance void [mscorlib]System.Reflection.AssemblyTitleAttribute::.ctor(string) = ( 01 00 0C 63 6E 62 6C 6F 67 5F 62 6F 77 65 6E 00   // ...cnblog_bowen.
                                                                                               00 )
   .custom instance void [mscorlib]System.Reflection.AssemblyDescriptionAttribute::.ctor(string) = ( 01 00 00 00 00 )
   .custom instance void [mscorlib]System.Reflection.AssemblyConfigurationAttribute::.ctor(string) = ( 01 00 00 00 00 )
   .custom instance void [mscorlib]System.Reflection.AssemblyCompanyAttribute::.ctor(string) = ( 01 00 18 4C 65 6E 6F 76 6F 20 28 42 65 69 6A 69   // ...Lenovo (Beiji
                                                                                                 6E 67 29 20 4C 69 6D 69 74 65 64 00 00 )          // ng) Limited..
   .custom instance void [mscorlib]System.Reflection.AssemblyProductAttribute::.ctor(string) = ( 01 00 0C 63 6E 62 6C 6F 67 5F 62 6F 77 65 6E 00   // ...cnblog_bowen.
                                                                                                 00 )
   .custom instance void [mscorlib]System.Reflection.AssemblyCopyrightAttribute::.ctor(string) = ( 01 00 2A 43 6F 70 79 72 69 67 68 74 20 C2 A9 20   // ..*Copyright ..
                                                                                                   4C 65 6E 6F 76 6F 20 28 42 65 69 6A 69 6E 67 29   // Lenovo (Beijing)
                                                                                                   20 4C 69 6D 69 74 65 64 20 32 30 31 30 00 00 )    //  Limited 2010..
   .custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string) = ( 01 00 00 00 00 )
   .custom instance void [mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 )
   .custom instance void [mscorlib]System.Runtime.InteropServices.GuidAttribute::.ctor(string) = ( 01 00 24 61 64 61 62 34 66 63 33 2D 33 33 64 35   // ..$adab4fc3-33d5
                                                                                                   2D 34 62 64 30 2D 39 61 32 61 2D 39 35 35 61 65   // -4bd0-9a2a-955ae
                                                                                                   66 38 35 33 31 62 37 00 00 )                      // f8531b7..
   .custom instance void [mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30 2E 30 2E 30 00 00 )             // ...1.0.0.0..
   .custom instance void [mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 29 2E 4E 45 54 46 72 61 6D 65 77 6F 72 6B   // ..).NETFramework
                                                                                                         2C 56 65 72 73 69 6F 6E 3D 76 34 2E 30 2C 50 72   // ,Version=v4.0,Pr
                                                                                                         6F 66 69 6C 65 3D 43 6C 69 65 6E 74 01 00 54 0E   // ofile=Client..T.
                                                                                                         14 46 72 61 6D 65 77 6F 72 6B 44 69 73 70 6C 61   // .FrameworkDispla
                                                                                                         79 4E 61 6D 65 1F 2E 4E 45 54 20 46 72 61 6D 65   // yName..NET Frame
                                                                                                         77 6F 72 6B 20 34 20 43 6C 69 65 6E 74 20 50 72   // work 4 Client Pr
                                                                                                         6F 66 69 6C 65 )                                  // ofile
 
   // --- The following custom attribute is added automatically, do not uncomment -------
   //  .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
 
   .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
   .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                              63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
   .hash algorithm 0x00008004
   .ver 1:0:0:0
}
.module Test6.exe
// MVID: {7020C5F0-2D89-4214-AD2C-E6BFBEC57CA1}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000003    //  ILONLY 32BITREQUIRED
// Image base: 0x030F0000
 
 
// =============== CLASS MEMBERS DECLARATION ===================
 
.class public auto ansi beforefieldinit Test6.CLRviaCSharp_6
        extends [mscorlib]System.Object
{
   .method private hidebysig static void  Main(string[] args) cil managed
   {
     .entrypoint
     // Code size       41 (0x29)
     .maxstack  1
     .locals init ([0] class Test6.BaseClass b,
              [1] class Test6.BaseClass s)
     IL_0000:  nop
     IL_0001:  call       void Test6.BaseClass::SShow()
     IL_0006:  nop
     IL_0007:  newobj     instance void Test6.BaseClass::.ctor()
     IL_000c:  stloc.0
     IL_000d:  newobj     instance void Test6.SubClass::.ctor()
     IL_0012:  stloc.1
     IL_0013:  ldloc.0
     IL_0014:  callvirt   instance void Test6.BaseClass::VShow()
     IL_0019:  nop
     IL_001a:  ldloc.1
     IL_001b:  callvirt   instance void Test6.BaseClass::VShow()
     IL_0020:  nop
     IL_0021:  ldc.i4.1
     IL_0022:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey(bool)
     IL_0027:  pop
     IL_0028:  ret
   } // end of method CLRviaCSharp_6::Main
 
   .method public hidebysig specialname rtspecialname
           instance void  .ctor() cil managed
   {
     // Code size       7 (0x7)
     .maxstack  8
     IL_0000:  ldarg.0
     IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
     IL_0006:  ret
   } // end of method CLRviaCSharp_6::.ctor
 
} // end of class Test6.CLRviaCSharp_6
 
.class public auto ansi beforefieldinit Test6.BaseClass
        extends [mscorlib]System.Object
{
   .method public hidebysig static void  SShow() cil managed
   {
     // Code size       13 (0xd)
     .maxstack  8
     IL_0000:  nop
     IL_0001:  ldstr      "Base class static method: SShow()!"
     IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
     IL_000b:  nop
     IL_000c:  ret
   } // end of method BaseClass::SShow
 
   .method public hidebysig newslot virtual
           instance void  VShow() cil managed
   {
     // Code size       13 (0xd)
     .maxstack  8
     IL_0000:  nop
     IL_0001:  ldstr      "Base class virtual method: VShow()!"
     IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
     IL_000b:  nop
     IL_000c:  ret
   } // end of method BaseClass::VShow
 
   .method public hidebysig specialname rtspecialname
           instance void  .ctor() cil managed
   {
     // Code size       7 (0x7)
     .maxstack  8
     IL_0000:  ldarg.0
     IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
     IL_0006:  ret
   } // end of method BaseClass::.ctor
 
} // end of class Test6.BaseClass
 
.class public auto ansi beforefieldinit Test6.SubClass
        extends Test6.BaseClass
{
   .method public hidebysig virtual instance void
           VShow() cil managed
   {
     // Code size       13 (0xd)
     .maxstack  8
     IL_0000:  nop
     IL_0001:  ldstr      "Sub class virtual method: VShow()!"
     IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
     IL_000b:  nop
     IL_000c:  ret
   } // end of method SubClass::VShow
 
   .method public hidebysig specialname rtspecialname
           instance void  .ctor() cil managed
   {
     // Code size       7 (0x7)
     .maxstack  8
     IL_0000:  ldarg.0
     IL_0001:  call       instance void Test6.BaseClass::.ctor()
     IL_0006:  ret
   } // end of method SubClass::.ctor
 
} // end of class Test6.SubClass
 
 
// =============================================================
 
// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file Test6.res

其中Main函数从63行开始。

71行的静态方法由call来调用的,78行和81行的虚方法则是由callvirt来调用的。

为了验证call使用非虚的方式来调用方法的,我们将生成的IL文件Test6.il中81行的callvirt改为call。

修改Test6.il后保存,然后用ilasm.exe来编译此IL文件为新的exe文件。

命令:ilasm .\Test6.il /res:Test6.res /output:Test6_new.exe

然后执行Test6_new.exe,发现最后一步也是调用基类的方法,无法表现出多态性。

image

其实我们在写C#代码时并不用关心call和callvirt,c#编译器会帮助我们选择合适的调用方法。

只是在分析IL时经常会遇到callvirt,这里记录下来方便以后查阅。



本文转自wang_yb博客园博客,原文链接:http://www.cnblogs.com/wang_yb/archive/2011/06/28/2092327.html,如需转载请自行联系原作者

目录
相关文章
|
3月前
|
C# Python
C# 笔记1 - 操作目录
C# 笔记1 - 操作目录
29 0
|
3月前
|
C# Python
C# 笔记3 - 重载一系列像python那样的print()方法
C# 笔记3 - 重载一系列像python那样的print()方法
27 1
|
3月前
|
存储 C# C++
C# 笔记2 - 数组、集合与与文本文件处理
C# 笔记2 - 数组、集合与与文本文件处理
45 0
|
10月前
|
存储 网络协议 Java
C# 快速入门笔记
C# 快速入门笔记
C# 快速入门笔记
|
C# 开发工具
C#滑动拼图验证码实现笔记
C# 是一个现代的、通用的、面向对象的编程语言,它是由微软(Microsoft)开发的,由 Ecma 和 ISO 核准认可的。突发奇想,动手开发一个C#滑动拼图验证码,下面是我开发过程的记录。
C#滑动拼图验证码实现笔记
|
SQL 开发框架 算法
【读书笔记】《Effective C#》50条建议笔记整理
对《Effective C#:改善C#代码的50个有效方法》一书整理的读书笔记。
28063 5
【读书笔记】《Effective C#》50条建议笔记整理
|
C# 数据库
C#编程-65:读取数据库DataReader对象复习笔记
C#编程-65:读取数据库DataReader对象复习笔记
C#编程-65:读取数据库DataReader对象复习笔记
|
C# 数据库
C#编程-65:数据库Command对象复习笔记
C#编程-65:数据库Command对象复习笔记
C#编程-65:数据库Command对象复习笔记
|
C# 数据库
C#编程-65:连接数据库复习笔记
C#编程-65:连接数据库复习笔记
C#编程-65:连接数据库复习笔记
C#编程-64:ADO.NET对象模型复习笔记
C#编程-64:ADO.NET对象模型复习笔记
C#编程-64:ADO.NET对象模型复习笔记