Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Resharper:IEnumerable的可能多重枚举_C#_Linq_Resharper_Ienumerable_Optimization - Fatal编程技术网

C# Resharper:IEnumerable的可能多重枚举

C# Resharper:IEnumerable的可能多重枚举,c#,linq,resharper,ienumerable,optimization,C#,Linq,Resharper,Ienumerable,Optimization,我正在使用新的Resharper版本6。在我的代码中的几个地方,它在一些文本下面划线,并警告我可能存在IEnumerable的多重枚举 我理解这意味着什么,并在适当的时候采纳了建议,但在某些情况下,我不确定这是否真的是一件大事 类似于以下代码: var properties = Context.ObjectStateManager.GetObjectStateEntry(this).GetModifiedProperties(); if (properties.Contains("Propert

我正在使用新的Resharper版本6。在我的代码中的几个地方,它在一些文本下面划线,并警告我可能存在IEnumerable的多重枚举

我理解这意味着什么,并在适当的时候采纳了建议,但在某些情况下,我不确定这是否真的是一件大事

类似于以下代码:

var properties = Context.ObjectStateManager.GetObjectStateEntry(this).GetModifiedProperties();
if (properties.Contains("Property1") || properties.Contains("Property2") || properties.Contains("Property3")) {
    ...
}
它在第二行的
properties
的每一处下方加了下划线,警告我正在多次枚举这个IEnumerable

如果我将
.ToList()
添加到第1行的末尾(将
属性
IEnumerable
转到
列表
),警告就会消失

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


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

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


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

我不知道您的
属性在这里到底是什么-但是如果它本质上表示一个未具体化的数据库查询,那么您的
if
语句将执行三个查询

我想最好是:

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

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

您确定它不会在属性上迭代三次并调用Contains()?这在编程上似乎是合乎逻辑的,但我确实理解,如果它能够优化它,只使用一次迭代,那么它将是更优化的。EDIT:gah,对不起,我读的是相反的…@jishi:重点是现在对
propertiesToFind
而不是
properties
@jishi:lambda表达式中只有一个对
Contains
的调用,所以它只会对每个元素调用一次
Contains
。。。但这是在数组上调用
Contains
。如果计算序列非常耗时(例如,它正在查看更大的序列并进行筛选),那么这将更加有效。SQL IN子句只有在属性为IQueryable时才可能发生。