readonly Func与方法,性能影响/引擎盖下的东西

时间:2012-01-22 23:05:57

标签: c# .net performance methods func

将实现引用透明方法作为静态只读Func而不是简单地作为方法,是否有任何性能影响?我个人认为Func版本更具可读性,但传统方式可能更有效。

此:

static readonly Func<DateTime, DateTime> TruncateDay =
  date => date.AddHours(-date.Hour)
              .AddMinutes(-date.Minute)
              .AddSeconds(-date.Second)
              .AddMilliseconds(-date.Millisecond);

static readonly Func<DateTime, DateTime> TruncateMonth =
  date => TruncateDay(date).AddDays(1 - date.Day);

static readonly Func<DateTime, DateTime> TruncateYear =
  date => TruncateMonth(date).AddMonths(1 - date.Month);

static readonly Func<DateTime, int> QuarterSwitch =
  date => Switch(date.Month % 3, 0,
            Case(1, 3),
            Case(2, 4),
            Case(0, 5));

对此:

static DateTime TruncateDay (DateTime date) 
{ 
  return date.AddHours(-date.Hour)
             .AddMinutes(-date.Minute)
             .AddSeconds(-date.Second)
             .AddMilliseconds(-date.Millisecond);
}

static DateTime TruncateMonth (DateTime date)
{ 
  return TruncateDay(date).AddDays(1 - date.Day);
}

static DateTime TruncateYear (DateTime date)
{
  return TruncateMonth(date).AddMonths(1 - date.Month);
}

static int QuarterSwitch (DateTime date)
{ 
  return Switch(date.Month % 3, 0,
           Case(1, 3),
           Case(2, 4),
           Case(0, 5));
}

这些内部如何表示?编译器将每个转换成什么?

4 个答案:

答案 0 :(得分:5)

在幕后,编译器为每个Func方法创建了2个额外成员:

  1. 一种静态方法,与传统方法基本相同。
  2. 与您的代理人类型相同的“缓存委托”字段。
  3. 缓存委托字段的原因是编译器需要这个代码中出现的匿名方法。在这种情况下,编译器不会优化掉字段。

    该类还需要一个静态构造函数来为每个方法初始化这两个字段。

    一些性能影响是:

    • 必须调用私有静态函数需要很小的开销。随着参数列表的大小增加,这种开销也会增加。
    • Func方法永远不能内联。对于非常小的方法,这可能会产生很大的不同。
    • 您班级的元数据将大约增加3倍。这不是免费的,但其效果难以量化。

    使用它的一些其他缺点是:

    • 无法进行重载。
    • 未在Intellisense中选取参数名称。
    • 它以多种方式违反了期望,包括方法在语句完成列表中显示为字段。

答案 1 :(得分:3)

在一个简单的循环中尝试你的TruncateDay,我得到的方法速度非常快 - 足够接近,使用该方法的最慢运行速度比代表速度慢,但仍然只是一致的代表往往只是性能稍差。

然后我尝试使用只返回传递给它的值的版本。我的计划是拥有一个绝对应该是无法使用的方法,并且方法版本比委托版本快5倍。显而易见的结论是,该方法确实已经内联,而代表则没有,尽管这当然是猜想。

但是,这足以表明至少有一些优化是针对不为代理人制作的方法。认为可能还有更多的东西并不是没有道理的。

答案 2 :(得分:2)

如果他们的身体本身便宜,静态方法会快得多。如果身体很贵,那就无所谓了。

JIT无法内联委托内容,必须使用间接调用。两者都很糟糕(对于便宜的方法)。

此外,从代码质量的角度来看,这是不可接受的:

  • 更多代码
  • 对于大多数人来说,因为他们习惯了传统风格而不太可读。
  • 没有重构支持
  • 反对传统习语
  • 更复杂

我强烈建议您在这种情况下采用传统方式。如果我是项目负责人,我不会在没有特殊原因的情况下容忍这样的代码。

答案 3 :(得分:0)

它帮助我。希望它会为你做同样的事情。

grid.Sort.Enabled = false;
grid.Data Source = _data source_;

//Add a single object to the beginning of the grid
grid.Nodes.Insert(0, _new_object_);

//Add a single object to the beginning of the binding list
I Binding List bl = ...;
bl.Insert(0, _new_object_);