由浅入深CIL系列:5.抛砖引玉:判断string是否为空的四种方法的CIL代码看看效率如何?
2011-07-04 11:17
274 查看
本节将接触几个新的CIL操作码如下
ldc.i4.0 将整数值 0 作为 int32 推送到计算堆栈上
Ceq 比较两个值。如果这两个值相等,则将整数值 1 (int32) 推送到计算堆栈上;否则,将 0 (int32) 推送到计算堆栈上。
Brtrue.s 如果 value 为 true、非空或非零,则将控制转移到目标指令(短格式)。
Brfalse.S 如果 value 为 false、空引用或零,则将控制转移到目标指令。
Callvirt 对对象调用后期绑定方法,并且将返回值推送到计算堆栈上。
Ldsfld 将静态字段的值推送到计算堆栈上。
源代码
一、在.NET有几种判断string是否为空的方法,也有两种判断值是否相等的方法。下面我们来看看:
二、下面我们看看上面的Cs代码生成的CIL代码如下:
4种方法的CIL分析
A.if (str1 == ""),在这里我们需要新构造一个""空字符,然后再调用System.String::op_Equality(string,string)函数对str1和空字符进行对比。
B.if (str1 == string.Empty),在这里我们通过string [mscorlib]System.String::Empty加载一个CIL代码为.field public static initonly string Empty的静态字段,然后让str1和这个静态字段做比较System.String::op_Equality(string,string),以确定是否为空。
C.if (str1.Length == 0),在这里我们调用[mscorlib]System.String::get_Length()函数获取到字符串长度,然后这个长度和0相对比
D.if (string.IsNullOrEmpty(str1)),这种方式直接调用系统的System.String::IsNullOrEmpty(string)函数直接比对出结果。
性能分析
下面我们通过using System.Diagnostics;命名空间下的Stopwatch对象来计算这4种调用方式所消耗的大概时间。
请看cs代码如下:
然后我们需要看看结果如何,为了提高精确度,我们运行多次结果,然后就知道哪种方式的效率最高。
下面我们来看在我的电脑上的运行时间情况如下面的图所示:
System.String::IsNullOrEmpty(string)
ldc.i4.0 将整数值 0 作为 int32 推送到计算堆栈上
Ceq 比较两个值。如果这两个值相等,则将整数值 1 (int32) 推送到计算堆栈上;否则,将 0 (int32) 推送到计算堆栈上。
Brtrue.s 如果 value 为 true、非空或非零,则将控制转移到目标指令(短格式)。
Brfalse.S 如果 value 为 false、空引用或零,则将控制转移到目标指令。
Callvirt 对对象调用后期绑定方法,并且将返回值推送到计算堆栈上。
Ldsfld 将静态字段的值推送到计算堆栈上。
源代码
一、在.NET有几种判断string是否为空的方法,也有两种判断值是否相等的方法。下面我们来看看:
class Program { static void Main(string[] args) { //判断字符串是否为空 string str1 = "MyWord"; if (str1 == "") ; if (str1 == string.Empty) ; if (str1 != null && str1.Length== 0) ; if (string.IsNullOrEmpty(str1)) ; } }
二、下面我们看看上面的Cs代码生成的CIL代码如下:
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // 代码大小 85 (0x55) .maxstack 2 //声明3个参数,分别是str1和bool值 .locals init ([0] string str1, [1] bool CS$4$0000) IL_0000: nop //推送对元数据中存储的"MyWord"字符串的新对象引用 IL_0001: ldstr "MyWord" //将"MyWord"压栈到参数0 IL_0006: stloc.0
//--------string空判断第一种方法 if (str1 == "") -------- //将"MyWord"从参数0处加载到计算堆栈上 IL_0007: ldloc.0 //推送对元数据中存储的""字符串的新对象引用 IL_0008: ldstr "" //通过System.String::op_Equality函数判断是否相等 IL_000d: call bool [mscorlib]System.String::op_Equality(string, string) //将整数值 0 作为 int32 推送到计算堆栈上 IL_0012: ldc.i4.0 //ceq比较两个值。如果这两个值相等,则将整数值 1 (int32)推送到计算堆栈上; //否则,将 0 (int32) 推送到计算堆栈上。 IL_0013: ceq //将true或者false的bool值弹出栈存到参数1去 IL_0015: stloc.1 //从参数1中加载数据到计算堆栈上去 IL_0016: ldloc.1 //如果 value 为 true、非空或非零,则将控制转移到目标指令(短格式)。 //也就是if判断中如果结果为true的话,则运行内部代码 IL_0017: brtrue.s IL_0019
//--------string空判断第二种方法 if (str1 == string.Empty) -------- IL_0019: ldloc.0 //Ldsfld 将静态字段的值推送到计算堆栈上。 IL_001a: ldsfld string [mscorlib]System.String::Empty IL_001f: call bool [mscorlib]System.String::op_Equality(string, string) IL_0024: ldc.i4.0 IL_0025: ceq IL_0027: stloc.1 IL_0028: ldloc.1 IL_0029: brtrue.s IL_002b
//--------string空判断第三种方法 if (str1!=null&&str1.Length == 0) -------- IL_002b: ldloc.0 //对象调用后期绑定方法,并且将返回值推送到计算堆栈上。<==> str1!=null IL_002c: brfalse.s IL_003c IL_002e: ldloc.0 //调用系统函数获取长度 IL_002f: callvirt instance int32 [mscorlib]System.String::get_Length() IL_0034: ldc.i4.0 IL_0035: ceq IL_0037: ldc.i4.0 IL_0038: ceq IL_003a: br.s IL_003d IL_003c: ldc.i4.1 IL_003d: stloc.1 IL_003e: ldloc.1 IL_003f: brtrue.s IL_0041
//--------string空判断第四种方法 if (string.IsNullOrEmpty(str1)) -------- IL_0041: ldloc.0 //直接调用系统System.String::IsNullOrEmpty(string)函数比对 IL_0042: call bool [mscorlib]System.String::IsNullOrEmpty(string) IL_0047: ldc.i4.0 IL_0048: ceq IL_004a: stloc.1 IL_004b: ldloc.1 IL_004c: brtrue.s IL_004e } // end of method Program::Main
4种方法的CIL分析
A.if (str1 == ""),在这里我们需要新构造一个""空字符,然后再调用System.String::op_Equality(string,string)函数对str1和空字符进行对比。
//--------string空判断第一种方法 if (str1 == "") -------- //将"MyWord"从参数0处加载到计算堆栈上 IL_0007: ldloc.0 //推送对元数据中存储的""字符串的新对象引用 IL_0008: ldstr "" //通过System.String::op_Equality函数判断是否相等 IL_000d: call bool [mscorlib]System.String::op_Equality(string, string) //将整数值 0 作为 int32 推送到计算堆栈上 IL_0012: ldc.i4.0 //ceq比较两个值。如果这两个值相等,则将整数值 1 (int32)推送到计算堆栈上; //否则,将 0 (int32) 推送到计算堆栈上。 IL_0013: ceq //将true或者false的bool值弹出栈存到参数1去 IL_0015: stloc.1 //从参数1中加载数据到计算堆栈上去 IL_0016: ldloc.1 //如果 value 为 true、非空或非零,则将控制转移到目标指令(短格式)。 //也就是if判断中如果结果为true的话,则运行内部代码 IL_0017: brtrue.s IL_0019
B.if (str1 == string.Empty),在这里我们通过string [mscorlib]System.String::Empty加载一个CIL代码为.field public static initonly string Empty的静态字段,然后让str1和这个静态字段做比较System.String::op_Equality(string,string),以确定是否为空。
//--------string空判断第二种方法 if (str1 == string.Empty) -------- IL_0019: ldloc.0 //Ldsfld 将静态字段的值推送到计算堆栈上。 IL_001a: ldsfld string [mscorlib]System.String::Empty IL_001f: call bool [mscorlib]System.String::op_Equality(string, string) IL_0024: ldc.i4.0 IL_0025: ceq IL_0027: stloc.1 IL_0028: ldloc.1 IL_0029: brtrue.s IL_002b
C.if (str1.Length == 0),在这里我们调用[mscorlib]System.String::get_Length()函数获取到字符串长度,然后这个长度和0相对比
//--------string空判断第三种方法 if (str1!=null&&str1.Length == 0) -------- IL_002b: ldloc.0 //对象调用后期绑定方法,并且将返回值推送到计算堆栈上。<==> str1!=null IL_002c: brfalse.s IL_003c IL_002e: ldloc.0 //调用系统函数获取长度 IL_002f: callvirt instance int32 [mscorlib]System.String::get_Length() IL_0034: ldc.i4.0 IL_0035: ceq IL_0037: ldc.i4.0 IL_0038: ceq IL_003a: br.s IL_003d IL_003c: ldc.i4.1 IL_003d: stloc.1 IL_003e: ldloc.1 IL_003f: brtrue.s IL_0041
D.if (string.IsNullOrEmpty(str1)),这种方式直接调用系统的System.String::IsNullOrEmpty(string)函数直接比对出结果。
//--------string空判断第四种方法 if (string.IsNullOrEmpty(str1)) -------- IL_0041: ldloc.0 //直接调用系统System.String::IsNullOrEmpty(string)函数比对 IL_0042: call bool [mscorlib]System.String::IsNullOrEmpty(string) IL_0047: ldc.i4.0 IL_0048: ceq IL_004a: stloc.1 IL_004b: ldloc.1 IL_004c: brtrue.s IL_004e
性能分析
下面我们通过using System.Diagnostics;命名空间下的Stopwatch对象来计算这4种调用方式所消耗的大概时间。
请看cs代码如下:
class Program { static void Main(string[] args) { //判断字符串是否为空 string str1 = "MyWord"; //第一种方法耗时计算 Stopwatch sw1 = new Stopwatch(); sw1.Start(); if (str1 == "") ; sw1.Stop(); //第二种方法耗时计算 Stopwatch sw2 = new Stopwatch(); sw2.Start(); if (str1 == string.Empty) ; sw2.Stop(); //第三种方法耗时计算 Stopwatch sw3 = new Stopwatch(); sw3.Start(); if (str1!=null&&str1.Length == 0) ; sw3.Stop(); //第四种方法耗时计算 Stopwatch sw4 = new Stopwatch(); sw4.Start(); if (string.IsNullOrEmpty(str1)) ; sw4.Stop(); Console.WriteLine(@"if (str1 == "")的判断时间是:" + sw1.Elapsed); Console.WriteLine(@"if (str1 == string.Empty)的判断时间是:" + sw2.Elapsed); Console.WriteLine(@"if (str1!=null&&str1.Length == 0)的判断时间是:" + sw3.Elapsed); Console.WriteLine(@"if (string.IsNullOrEmpty(str1)) 的判断时间是:" + sw4.Elapsed); Console.ReadLine(); }
然后我们需要看看结果如何,为了提高精确度,我们运行多次结果,然后就知道哪种方式的效率最高。
下面我们来看在我的电脑上的运行时间情况如下面的图所示:
System.String::IsNullOrEmpty(string)
.method public hidebysig static bool IsNullOrEmpty(string 'value') cil managed { // 代码大小 15 (0xf) .maxstack 8 IL_0000: ldarg.0 IL_0001: brfalse.s IL_000d IL_0003: ldarg.0 IL_0004: callvirt instance int32 System.String::get_Length() IL_0009: ldc.i4.0 IL_000a: ceq IL_000c: ret IL_000d: ldc.i4.1 IL_000e: ret } // end of method String::IsNullOrEmpty
相关文章推荐
- 由浅入深CIL系列:5.抛砖引玉:判断string是否为空的四种方法的CIL代码看看效率如何?
- 由浅入深CIL系列:4.抛砖引玉:使用CIL来分析string类型在.NET运算中的性能和避免装箱
- 由浅入深CIL系列:4.抛砖引玉:使用CIL来分析string类型在.NET运算中的性能和避免装箱
- java中判断string是否为空的三种方法——效率比较
- 如何判断字符串是否为空串?string.length的优越性
- 如何通过代码判断手机中是否有SIM卡
- Android应用程序获取ROOT权限的方法(android中如何通过代码检测是否有root权限?)
- JS如何判断是否为ie浏览器的方法(包括IE10、IE11在内)
- C#判断程序是否是管理员权限运行的方法代码示例
- @V@ java代码笔记2010-06-12:java控制台输入各类型类实现;以及判断输入字符串里面是否有数字的两种方法:方法1:转换成字符数组;方法2:正则表达式。
- 如何判断程序是否重复运行的几种方法
- 实测如何使用c#代码判断服务器是否安装iis
- Python实现判断一行代码是否为注释的方法
- 黄聪:如何判断VS开发C#是否为设计模式,以免编译之前操作窗体设计器代码自动运行
- 如何判断一个String是否能转换为数字
- 判断无向图是否有回路有四种方法
- 如何判断团队是否真正实施Scrum? —— Scrum方法二十问
- StringUtils 工具类中判断一个string类型的值是否为空的几种方法
- C++中判断string是否为整数及其转换方法
- 判断java String中是否有汉字的方法