缓存一个IEnumerable vs List以进行延迟初始化

本文关键字:List 初始化 延迟 vs IEnumerable 一个 缓存 | 更新日期: 2023-09-27 18:19:33

我有一个简单的缓存类,它可以检索并存储您传递给它的任何数据。这个类只有"Get(字符串键)"answers"Store(字符串键,对象数据)"两个操作。我使用这个类来存储昂贵的对象并快速检索它们。

想象一下,我想存储一个数组。据我所知,IEnumerable实现本质上是惰性实例化的。我的问题是:如果我将一个IEnumerable变量存储到Cache类(即LINQ查询的结果集),这个类是否会在处理了所有元素的情况下存储,或者每次我检索存储的IEnumeraable时,我都必须经过所有隐含的处理才能生成该IEnumerable?我应该使用"ToList()"来触发初始化吗?

注意:我没有访问这个缓存类的源代码的权限,我只知道它存储和检索对象。

缓存一个IEnumerable vs List以进行延迟初始化

IEnumerable是一个接口,而不是一个类。接口背后的实现定义了它的行为。

如果在IEnemable上调用ToList()<>您得到一个列表<>,而且是IEnumerable<>因为List实现了该接口。

将指针存储为IEnumerable<>并且对其进行迭代与对列表进行迭代相同。

如果IEnumerable<>是迭代器的结果,每次IEnumerable<>执行实现时访问。

示例:采用以下功能:

public IEnumerable<int> Generator(int max)
{
   for (var i = 0; i < max; i++)
   {
       yield return someExpensiveFunction();
   }
}

将其用作

var cache = Generator(100);
for (var i = 0; i < 2; i++)
{
   foreach (var i in cache)
   {
      //ops
   }
}

这将对Generator(==IEnumerable<>)求值两次。

var cache = Generator(100).ToList();
for(var i = 0; i < 2; i++
{
   foreach(var i in cache)
   {
      //ops
   }
}

这将只对Generator(==IENumerable<>)求值一次。

I.E.缓存IEnumerable<>如果你通过调用ToArray()、ToList()等使其成为"混凝土",那么它并不昂贵。

圆顶附加指南。如果您将枚举对象转换为列表并存储它们,那么最好将存储变量声明为列表。这是为了向您的用户和/或同事记录其存储模型。公共类/接口上的函数或属性的结果应该是Collection

class X
{
   private List<int> _cache;
   public void UpdateCache(IEnumerable<int> items)
   {
     _cache = items.ToList();
   }
   public ICollection<T> Cache
   {
      get{ return _cache; }
   }
   //even better
   public ReadOnlyCollection<T> Items
   {
      get { return new ReadonlyCollection(_cache); }
   }
}