【问题标题】:Is it worth caching a member struct?是否值得缓存成员结构?
【发布时间】:2015-08-11 17:42:34
【问题描述】:

我有一个类似这样的属性:

DateTime MinDate
{
    get { return new DateTime(2005, 3, 25); }
}

我担心每次调用Derived.MinDate 都会构造一个新的DateTime,所以我希望有一个只构造一次的底层_MinDate

private readonly DateTime _MinDate = new DateTime(2005, 3, 25);

DateTime MinDate
{
    get { return _MinDate; }
}

但这是否有任何影响,因为DateTime 无论如何都是一个结构? 场景 1: MinDate 构造一个新的 DateTime,然后将其复制给调用者。 场景二_MinDate被复制到MinDate,被复制到调用者。这两种情况同样低效,对吧?

【问题讨论】:

  • 您是否希望制造数百万个这样的对象?
  • 不,第二个例子效率更高,因为 JIT 会内联属性 getter,从而消除第二个复制操作。

标签: c# caching struct value-type


【解决方案1】:

在内部,DateTime(Int32, Int32, Int32) 构造函数非常便宜:它执行简单的乘法运算,将年、月和日转换为内部 64 位“Tick”值。

AFAIK CLR 不缓存确定性结构构造函数实例(但这将是一个很好的优化!)。

但是,如果你每秒调用构造函数数百次,我只会缓存这个值,但如果你真的想要,那么这个工作:

private static readonly DateTime _minDate = new DateTime( 2005, 3, 25 );
protected override DateTime MinDate { get { return _minDate; } }

【讨论】:

    【解决方案2】:

    几乎正确;几乎没有理由这样做。

    通过缓存结构,您需要复制缓存值的字节。

    通过构造它,你需要调用构造函数,它会设置结构体的字段。

    如果构造函数做昂贵的工作,缓存可能有用。

    DateTime constructor 做了很多工作,所以如果你多次调用该属性,它可能是值得的。
    但是,只有在实际发现性能问题时才应该这样做。

    【讨论】:

      【解决方案3】:

      您对传递给另一个变量时被复制的概念是正确的,因为 DateTime 是一个结构。

      这是实现目标的一种方法:-

      abstract class Base
      {
          protected abstract void GetMinDate (ref DateTime minDate);
      }
      
      class Derived
      {
          private static readonly DateTime _MinDate;
          static Derived()
          {
             _MinDate = new DateTime(2005, 3, 25);
          }
          protected override void GetMinDate (ref DateTime minDate);
          {
              minDate = _MinDate;
          }
      }
      

      GetMinDate 将始终通过 ref 返回最小日期,这将是调用者发出的复制或不复制的问题。

      【讨论】:

      • +1 用于考虑(虽然很小)性能开销的解决方法;这在处理大型结构时肯定很有用。
      【解决方案4】:

      从 C# 6.0 开始,现在有一种更简单的方法可以使用自动实现的属性初始值设定项:

      DateTime MinDate { get; } = new DateTime(y, m, d);
      

      编辑:这实际上是该功能的预期用途,并且支持字段由编译器自动生成readonly;事实上,您可以在构造函数中对它们进行set 操作。它们被称为“getter-only auto-properties”。详情请见here

      【讨论】:

        猜你喜欢
        • 2012-10-21
        • 1970-01-01
        • 1970-01-01
        • 2017-06-16
        • 1970-01-01
        • 2016-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多