我有一个简单的缓存类,可以检索并存储您传递给它的任何数据。该类具有的唯一操作是“Get(字符串键)”和“Store(字符串键,对象数据)”。我使用这个类存储昂贵的对象并快速检索它们。
想象一下,我想存储一个数组。据我所知,IEnumerable实现本质上是懒惰实例化的。我的问题是:如果我将一个IEnumerable变量存储到该Cache类(即LINQ查询的结果集),那么这个类是否会被存储并处理其所有元素,或者每当我检索到存储的IEnumerable时我将不得不经历所有处理隐含生成IEnumerable?我应该使用“ToList()”来触发初始化吗?
注意:我无法访问此Cache类的源代码,我只知道它存储和检索对象。
答案 0 :(得分:3)
IEnumerable是一个接口,而不是一个类。接口背后的实现定义了它的行为。
如果您在IEnemerable<>上调用ToList()你得到一个List<>,还有一个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&lt;&gt;)两次。
var cache = Generator(100).ToList();
for(var i = 0; i < 2; i++
{
foreach(var i in cache)
{
//ops
}
}
这将仅评估Generator(== IENumerable&lt;&gt;)一次。
即。缓存IEnumerable&lt;&gt;如果你做到具体的话,那就不贵了。通过调用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); }
}
}