判断字符串是否为空经常用到String.InNullOrEmpty方法,今天想试试它的速度有多快,结果遇到了一个有点奇怪的问题。
用Reflector把String.InNullOrEmpty方法的代码反射出来复制到自己的代码中去调用和直接调用String.InNullOrEmpty的速度竟然会相差3-4倍。而如果把String.Format反射并复制到自己的代码中调用却和直接调用String.Format没有多大区别。代码如下,请各位帮忙分析一下。using System;namespace ConsoleApplication1
{
    class Program
    {
        static DateTime startTime;        static void Main(string[] args)
        {
            string str = "hello";
            for (int i = 0; i < 10; i++)
            {
                RunItInTwoWays(str);
                Console.WriteLine("----------------");
            }
            Console.ReadLine();
        }        private static void RunItInTwoWays(string str)
        {
            Start();
            for (int i = 0; i < 10000000; i++)
            {
                string.IsNullOrEmpty(str);
            }
            PrintTimeSpan();            Start();
            for (int i = 0; i < 10000000; i++)
            {
                IsNullOrEmpty(str);
            }
            PrintTimeSpan();
        }        private static void Start()
        {
            startTime = DateTime.Now;
        }        private static void PrintTimeSpan()
        {
            TimeSpan elapsedTime = DateTime.Now - startTime;
            Console.WriteLine(elapsedTime);
        }        public static bool IsNullOrEmpty(string value)
        {
            if (value != null)
            {
                return (value.Length == 0);
            }
            return true;
        }
    }
}

解决方案 »

  1.   

    Reflector 这个东西会影响性能。
      

  2.   

    查不到10倍 
    也就3倍的样子
    string.IsNullOrEmpty(str);
    这个确实会快些反汇编 IsNullOrEmpty跟不进去不知道IsNullOrEmpty 是怎么实现的
      

  3.   

    你直接return true也一样。原因不详。可能是因为你的方法是动态调用的。系统的是编译过的。就像正则、lambda直接写好的,调用速度不如加上编译选项后的。
      

  4.   

    试了一下,直接return true差的要少一些。
    方法是动态调用的,但是应该只有第一次调用的时候才会JIT啊
      

  5.   

    用reflector可以看到啊。[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
    public static bool IsNullOrEmpty(string value)
    {
        if (value != null)
        {
            return (value.Length == 0);
        }
        return true;
    }  
      

  6.   

    就用reflector啊。
    找到mscorlib程序集,然后是System命名空间,然后string类型下的IsNullOrEmpty方法。
      

  7.   

    有可能是reflector在反编译时没有完全反编译出来某些编译属性(这个是无法避免的)
      

  8.   

    这才是微软公布的源代码中的 IsNullOrEmptypublic static bool IsNullOrEmpty(String value) { 
       return (value == null || value.Length == 0); 
    }
      

  9.   

    还没想通?提醒你一下,你复制的那段代码要多初始化两个bool变量,21楼的代码要多初始化一个bool变量...自然地,执行指令也要多几条...不要纠缠在这种无足轻重的表明现象上,若真想了解就去看CLR原理...ps:测试也是很有学问的,比如不要用DateTime.Now这种精度极低的时钟、不要乱用循环...
      

  10.   

    楼主,你是用反编译得到的源代码的,还是用反射得到源代码的。 前者我明白, 后者我就不知道了,我知道反射可以的程序的结构,比如构造函数是什么,比如有哪些公共方法。反射也能得到源代码的吗,我找了找google, 没找到具体做法。你说的reflector 是个反编译工具软件的名字吗
      

  11.   

    哦,不好意思,我指的就是用reflector这个工具获取的代码。
      

  12.   

    刚才又试了一下把Reflector得出的IL用ILASM编译成程序集,再调用,还是有差距。
      

  13.   


    .method public hidebysig static bool IsNullOrEmpty(string 'value') cil managed
    {
        .maxstack 8
        L_0000: ldarg.0 
        L_0001: brfalse.s L_000d
        L_0003: ldarg.0 
        L_0004: callvirt instance int32 System.String::get_Length()
        L_0009: ldc.i4.0 
        L_000a: ceq 
        L_000c: ret 
        L_000d: ldc.i4.1 
        L_000e: ret 
    }编译的就是这段IL。
      

  14.   

    你是在debug下测的吧?release下会快不少
      

  15.   


    谢谢,刚才试了一下,release anycpu编译的,在IDE之外运行的,直接调用String.IsNullOrEmpty和调用自己编译IL得到的程序集速度基本一致。
      

  16.   

    还是有点奇怪,微软当初实现String.IsNullOrEmpty的时候是直接用IL写的?还是他们用了什么优化的编译选项?
      

  17.   

    是啊,用Reflector反编译出来的C#确实不是和原来的一样的。
    但是IL应该是一样的。
      

  18.   

    是你测试环境的问题,跟reflector出来的代码没关系
      

  19.   


    reflector出来的C#再次编译为IL是和原始的不一样
      

  20.   

    PS:在没有选optimize code的情况下
      

  21.   

    il代码不同,c#代码还是同一份代码(当然不是说每一个字符都一样),只是编译选项不同