我有一个简单的缓存类,用于检索和存储您传递给它的任何数据。此类唯一的操作是“Get(string key)”和“Store(string key, object data)”。我使用此类来存储昂贵的对象并快速检索它们。
假设我想存储一个数组。据我所知,IEnumerable 实现本质上是惰性实例化的。我的问题是:如果我将一个 IEnumerable 变量存储到该 Cache 类(即 LINQ 查询的结果集),该类是否会存储其所有已处理的元素,或者每次我检索存储的 IEnumerable 时我都必须完成所有处理暗示生成那个 IEnumerable?我应该使用“ToList()”来触发初始化吗?
注意:我无权访问此缓存类的源代码,我只知道它存储和检索对象。
最佳答案
IEnumerable 是一个接口(interface)而不是一个类。接口(interface)背后的实现定义了它的行为。
如果您在 IEnemerable<> 上调用 ToList(),您会得到一个 List<>,但也会得到一个 IEnumerable<>,因为 List 实现了该接口(interface)。
将指针存储为 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
}
}
这将计算生成器 (==IEnumerable<>) 两次。
var cache = Generator(100).ToList();
for(var i = 0; i < 2; i++
{
foreach(var i in cache)
{
//ops
}
}
这只会对生成器 (==IENumerable<>) 求值一次。
即如果您通过调用 ToArray()、ToList() 等使其“具体”,那么缓存 IEnumerable<> 并不昂贵。
圆顶附加指导。如果将可枚举转换为列表并存储它们,最好将存储变量声明为列表。这是为了向您的用户和/或同事记录它的存储模型。 公共(public)类/接口(interface)上的函数或属性的结果应该是 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); }
}
}
关于c# - 缓存 IEnumerable 与 List 以进行延迟初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25530612/