Jon Skeet的Edulinq - 空数组缓存

时间:2013-02-06 16:21:11

标签: c# caching

我正在经过Jon Skeet的Edulinq,我遇到了以下代码,第23页,他为Linq的Empty()运算符实现了缓存机制

private static class EmptyHolder<T>
{
   internal static readonly T[] Array = new T[0];
}

我的问题是,这实际上如何缓存Array变量?

可选地,它如何在CLR中起作用?

编辑:在此之后,他提到了反对返回数组的反抗。为什么有人不返回一个数组(即使它是0大小?)?

2 个答案:

答案 0 :(得分:14)

  

我的问题是,这实际上如何缓存Array变量?

CLR按类型参数缓存它。基本上,EmptyHolder<int>是与EmptyHolder<string>等不同的类型,并且每个具体类型会调用类型初始化程序(由CLR自动调用)。

所以:

var x = EmptyHolder<string>.Array; // Needs to construct the empty string[] array
var y = EmptyHolder<string>.Array; // No extra work! x and y have the same value
var z = EmptyHolder<int>.Array; // This constructs an empty array for int[]
  

可选地,它如何在CLR中起作用?

这是一个我不太了解的实现细节,我很害怕。但基本上这是所有关于CLR如何做的事情:)

  

编辑:在此之后,他提到了反对返回数组的反抗。为什么有人不返回数组(即使它是0大小?)?

嗯,有评论:

  

数组方法不是很好:人们将错误地依赖返回值作为数组,尽管没有记录。

我个人认为这不是一个问题,但编写替代实现很有趣:)

答案 1 :(得分:0)

每次为T的第一次调用EmptyHolder.Empty()时,都必须为EmptyHolder调用静态构造函数。

现在它看起来没有静态构造函数,对吧?错误。该课程可以改写为......

private static class EmptyHolder<T>
{
   static EmptyHolder<T>()
   {
       Array = new T[0];
   }
   internal static readonly T[] Array;

   public IEnum<T> Empty();
}

现在,后续运行的Empty不会调用静态构造函数(除非使用不同的T)。

就像我可能批评Jon Skeet一样,这是一个值得关注的小优化。