博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

怎样判断字符串为空,最快?

Posted on 2005-03-30 11:15  Hon Young  阅读(5951)  评论(4)    收藏  举报
最近看到一些帖子在讨论哪种方法判断string为空时最快,我也发表一下自己的想法。

大概有三种方法判断string为空:
1.str.Lenght == 0
2.str == string.Empty
3.str == ""

我们先来写一段代码(用C#):
   string str ="";
  
   if(str.Length == 0)
   {
    MessageBox.Show("Eqauls 0");
   }
   if(str == string.Empty)
   {
    MessageBox.Show("Eqauls Empty");
   }
   if(str == "")
   {
    MessageBox.Show("Eqauls Space");
   }
这段代码经过编译后,生成的中间语言(MSIL)代码如下:
      .maxstack 2
      .locals (
            string text1)
      L_0000: ldstr ""
      L_0005: stloc.0                第一种方法
      L_0006: ldloc.0
      L_0007: callvirt instance int32 string::get_Length()
      L_000c: brtrue.s L_0019
      L_000e: ldstr "Eqauls 0"
      L_0013: call [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string)
      L_0018: pop
      L_0019: ldloc.0                第二种方法
      L_001a: ldsfld string [mscorlib]System.String::Empty
      L_001f: call bool string::op_Equality(string, string)
      L_0024: brfalse.s L_0031
      L_0026: ldstr "Eqauls Empty"
      L_002b: call [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string)
      L_0030: pop
      L_0031: ldloc.0                第三种方法
      L_0032: ldstr ""
      L_0037: call bool string::op_Equality(string, string)
      L_003c: brfalse.s L_0049
      L_003e: ldstr "Eqauls Space"
      L_0043: call [System.Windows.Forms]System.Windows.Forms.DialogResult [System.Windows.Forms]System.Windows.Forms.MessageBox::Show(string)
      L_0048: pop
      L_0049: ret
注意L_0007代码是获取的字符串的长度,然后比较是否与0相等,这样是非常快的。
下面两种方法(注意颜色标记的部分)不同的是,第2种方法load的是string的静态成员Empty,而第三种方法Load的是字符串常量“”,剩下的比较工作交给string::op_Equality(string, string)
进行比较,我们来看一下这个方法的IL代码:

.method public hidebysig specialname static bool op_Equality(string a, string b) cil managed
{
      // Code Size: 8 byte(s)
      .maxstack 8
      L_0000: ldarg.0 
      L_0001: ldarg.1 
      L_0002: call bool string::Equals(string, string) 直接把参数转交给string::Equals进行比较
      L_0007: ret 
}
.method public hidebysig static bool Equals(string a, string b) cil managed
{
      // Code Size: 22 byte(s)
      .maxstack 8
      L_0000: ldarg.0 
      L_0001: ldarg.1 
      L_0002: bne.un.s L_0006         比较两个变量是否引用的同一个地址
      L_0004: ldc.i4.1                如果相等则返回ture(即为1)
      L_0005: ret 
      L_0006: ldarg.0 
      L_0007: brfalse.s L_000c        判断第一个参数是否为NULL,为NULL则返回False
      L_0009: ldarg.1 
      L_000a: brtrue.s L_000e         判断第二个参数是否不为NULL,为NULL则返回False
      L_000c: ldc.i4.0 
      L_000d: ret 
      L_000e: ldarg.0 
      L_000f: ldarg.1 
      L_0010: callvirt instance bool string::Equals(string) 剩下的交给真正的比较函数
      L_0015: ret 
}
.method public hidebysig instance bool Equals(string value) cil managed internalcall
{
}






由此可以看出来第2种和第3种方法谁快谁慢,还不一定。
如果变量str付值为Empty,则肯定第2种方法快,str == string.Empty,两个变量引用的是同一个静态变量。
如果变量str付值为"",则肯定第3种方法快,str == "",两个变量引用的是同一个常量值。
如果变量str付值为其它之,则结果也不一定,要看bool string::Equals(string)方法了,但是这个方法不能看到IL代码的。:-)
总起来说,方法最快的肯定是str.Lenght == 0,建议大家以后比较字符串是否为空,一定要用这个方法。