6

我写了以下代码:

IEnumerable<string> blackListCountriesCodes = 
pair.Criterion.CountriesExceptions.Select(countryItem => countryItem.CountryCode);

IEnumerable<string> whiteListCountriesCodes = 
pair.Criterion.Countries.Select(countryItem => countryItem.CountryCode);

return (!blackListCountriesCodes.Contains(Consts.ALL.ToString()) &&
        !blackListCountriesCodes.Contains(country) &&
        (whiteListCountriesCodes.Contains(Consts.ALL.ToString()) ||
        whiteListCountriesCodes.Contains(country)));

resharper 向我显示警告: Possible duplicate enumeration of IEnumerable

这是什么意思?为什么这是一个警告?

4

3 回答 3

9

LINQ 查询会延迟它们的执行,直到您对结果进行处理。在这种情况下,对同一个集合调用Contains()两次可能会导致结果被枚举两次,这取决于查询,可能会导致性能问题。

您可以通过简单地ToList()在查询结束时添加一个调用来解决这个问题,这将强制执行查询并一次性存储结果。

于 2012-12-20T15:38:56.693 回答
1

这意味着您的代码可能会枚举blackListCountriesCodeswhiteListCountriesCodes多次。由于 LINQ 使用延迟评估,这可能会导致速度变慢,尤其是当它pair有大量数据并且Where子句很复杂时(不过,它看起来并不适用于您的情况)。

您可以通过将枚举“具体化”到列表中来消除警告(以及所谓的缓慢),如下所示:

var blackListCountriesCodes = 
    pair.Criterion.CountriesExceptions.Select(countryItem => countryItem.CountryCode).ToList();

var whiteListCountriesCodes = 
    pair.Criterion.Countries.Select(countryItem => countryItem.CountryCode).ToList();
于 2012-12-20T15:39:05.907 回答
1

这意味着您可能会计算IEnumerable两次(或更多)的内容。如果这很昂贵,例如调用数据库,这对性能不利。如果基础来源是 aList<T>并且有一个简单的投影或其他不昂贵的东西,这不是问题。

您当然可以重写表达式以仅使用一次枚举。

!blackListCountriesCodes.Contains(Consts.ALL.ToString())
    && !blackListCountriesCodes.Contains(country)

可以改写为

!blackListCountriesCodes
    .Where(blcc => blcc == Consts.ALL.ToString() || blcc == country).Any()
于 2012-12-20T15:39:59.140 回答