缓存一个IEnumerable vs List以进行延迟初始化
本文关键字:List 初始化 延迟 vs IEnumerable 一个 缓存 | 更新日期: 2023-09-27 18:19:33
我有一个简单的缓存类,它可以检索并存储您传递给它的任何数据。这个类只有"Get(字符串键)"answers"Store(字符串键,对象数据)"两个操作。我使用这个类来存储昂贵的对象并快速检索它们。
想象一下,我想存储一个数组。据我所知,IEnumerable实现本质上是惰性实例化的。我的问题是:如果我将一个IEnumerable变量存储到Cache类(即LINQ查询的结果集),这个类是否会在处理了所有元素的情况下存储,或者每次我检索存储的IEnumeraable时,我都必须经过所有隐含的处理才能生成该IEnumerable?我应该使用"ToList()"来触发初始化吗?
注意:我没有访问这个缓存类的源代码的权限,我只知道它存储和检索对象。
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); }
}
}