Resharper:可能多次枚举IEnumerable

Ros*_*oss 37 c# linq resharper optimization ienumerable

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

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

如下面的代码所示:

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

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

如果我添加.ToList()到第1行的末尾(properties从a IEnumerable<string>转到a List<string>),警告就会消失.

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

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

Jon*_*eet 41

我不知道你到底在properties究竟是什么- 但如果它本质上代表一个非物质化的数据库查询,那么你的if语句将执行三个查询.

怀疑这样做会更好:

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

这将逻辑上只迭代序列一次 - 如果涉及数据库查询,它可能只能使用SQL"IN"子句在单个查询中在数据库中完成所有操作.


jis*_*shi 6

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

由于扩展方法只知道它是一个IEnumerable,它可能不能利用任何内置方法,Contains()即使理论上可以识别已知类型并相应地转换它们以便利用它们.