Resharper:可能多次枚举IEnumerable

时间:2011-07-06 08:54:12

标签: c# linq resharper ienumerable optimization

我正在使用新的Resharper版本6.在我的代码中的几个地方,它强调了一些文本,并警告我可能存在可能多次枚举IEnumerable

我理解这意味着什么,并在适当的时候采纳了建议,但在某些情况下我不确定这实际上是一个大问题。

如下面的代码所示:

var properties = Context.ObjectStateManager.GetObjectStateEntry(this).GetModifiedProperties();
if (properties.Contains("Property1") || properties.Contains("Property2") || properties.Contains("Property3")) {
    ...
}

它强调了第二行中每个properties的提及,警告我多次枚举这个IEnumerable。

如果我将.ToList()添加到第1行的末尾(将propertiesIEnumerable<string>转为List<string>),警告就会消失。

但是,当然,如果我将它转换为List,那么它将枚举整个IEnumerable以首先构建List,然后根据需要枚举List以查找属性(即1个完整枚举,以及3部分枚举)。而在我的原始代码中,它只进行了3次部分枚举。

我错了吗?这里最好的方法是什么?

2 个答案:

答案 0 :(得分:41)

我不确切知道你的properties到底在哪里 - 但如果它实际上代表了一个非物质化的数据库查询,那么你的if语句将执行三个查询。

怀疑最好这样做:

string[] propertiesToFind = { "Property1", "Property2", "Property3" };
if (properties.Any(x => propertiesToFind.Contains(x))
{
     ...
}

逻辑只会迭代序列一次 - 如果涉及数据库查询,它可能只能使用SQL“IN”子句在数据库中完成所有操作一个查询。

答案 1 :(得分:6)

如果在IEnumerable上调用Contains(),它将调用扩展方法,该方法将遍历项目以便找到它。 IList具有Contains()的实际实现,它可能比通过值的常规迭代更有效(它可能有一个带有哈希的搜索树?),因此它不会与IList发出警告

由于扩展方法只知道它是IEnumerable,它可能无法利用Contains()的任何内置方法,即使理论上可以识别已知类型和强制转换因此,为了利用它们。