获取调用方法名称 - Reflection和CallerInfo属性

时间:2014-04-08 06:49:34

标签: c# .net reflection .net-4.5 callermembername

只是标记了使用StackTraceCallerInfo Attributes的效果。

令人震惊的是,我发现尽管我读到StackTrace的所有地方,使用To get the caller method name, the preferred approach is CallerInfo attributes要快得多。

public class Program
    {
        public static void Main(string[] args)
        {
          Method1();  
        }

         static void Method1([CallerMemberName]string memberName = "")
         {
            double stackTraceTimings = 0;
            var sw = new Stopwatch();

            foreach(var item in Enumerable.Range(1,1000).ToList())
            {
               sw.Start();
               var callerName = new StackFrame(1).GetMethod().Name;
               sw.Stop();
               stackTraceTimings += sw.Elapsed.TotalMilliseconds;
            }

            Console.WriteLine("Elapsed Time for retrieving the caller name using StackFrame in 1000 iterations ={0}",stackTraceTimings/1000);

            stackTraceTimings = 0;
            foreach(var item in Enumerable.Range(1,1000).ToList())
            {
                sw.Start();
                var callerName = (memberName);
                sw.Stop();
                stackTraceTimings += sw.Elapsed.TotalMilliseconds;
            }

            Console.WriteLine("Elapsed Time for retrieving the caller name using callerInfo Attribute in 1000 iterations ={0}",stackTraceTimings/1000);
        }

输出: 在1000次迭代中使用StackFrame检索呼叫者姓名的经过时间= 9.48074760000001

在1000次迭代中使用callerInfo属性检索来电者姓名的经过时间= 21.7074064

我误解了什么吗?使用CallerInfo属性是首选方法吗?

感谢以下答案指出。

我必须每次在循环中重新启动计时器。

那么,谁赢了?如下面的答案所说,CallerInfo。因为,它是一个编译时功能,速度更快。

在1000次迭代中使用StackFrame检索来电者姓名的经过时间= 0.00762619999999992

在1000次迭代中使用callerInfo属性检索来电者姓名的已用时间= 0.00639420000000002

我使用下面的代码(修订版)并得到了上述结果。

 public class Program
    {
        public static void Main(string[] args)
        {
          Method1();  
        }

         static void Method1([CallerMemberName]string memberName = "")
         {
            double stackTraceTimings = 0;
            var sw = new Stopwatch();

            foreach(var item in Enumerable.Range(1,1000).ToList())
            {
               sw.Start();
               var callerName = new StackFrame(1).GetMethod().Name;
               sw.Stop();
               Console.Write(callerName);
               sw.Restart();
               stackTraceTimings += sw.Elapsed.TotalMilliseconds;
            }

            Console.WriteLine("Elapsed Time for retrieving the caller name using StackFrame in 1000 iterations ={0}",stackTraceTimings/1000);


            stackTraceTimings = 0;
            foreach(var item in Enumerable.Range(1,1000).ToList())
            {
                sw.Start();
                var callerName = (memberName);
                Console.Write(callerName);
                sw.Stop();
                sw.Restart();

                stackTraceTimings += sw.Elapsed.TotalMilliseconds;
            }

            Console.WriteLine("Elapsed Time for retrieving the caller name using callerInfo Attribute in 1000 iterations ={0}",stackTraceTimings/1000);
        }
    }

1 个答案:

答案 0 :(得分:1)

您必须在第二次循环之前重置计时器。 sw.Start从第一次循环后的状态开始Stopwatch,因此第二个结果实际上是StackTrace和基于属性的解决方案汇总在一起的时间。

CallerMethodName是编译类型的功能,它肯定会更快。

结果中CallerMethodName的固定代码时间为:

21.7074064 - (9.48074760000001 * 2)= 2.7459111999999806

那要快得多,不是吗?

第一次减去两次:一次是缺少Reset来电,一次是+=而不是=

<强>更新

这些结果似乎太大了。 您确定使用的是从Visual Studio外部运行的版本构建吗?我认为不是,因为否则您会得到完全相同的结果:callerName永远不会使用过,可能会优化到无操作(至少在第二种情况下)。