IEnumerable的可能重复枚举



我写了以下代码:

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

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

LINQ查询将延迟其执行,直到您对结果执行某些操作。在这种情况下,在同一个集合上调用两次Contains()可能会导致结果被枚举两次,这可能会导致性能问题,具体取决于查询。

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

这意味着您的代码可能多次枚举blackListCountriesCodeswhiteListCountriesCodes。由于LINQ使用延迟求值,这可能会导致速度变慢,特别是当pair有大量数据,而Where子句很复杂时(尽管看起来这些都不适用于您的情况)。

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

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

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

当然可以重写表达式,使其只使用一次枚举对象。

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

可以重写为

!blackListCountriesCodes
    .Where(blcc => blcc == Consts.ALL.ToString() || blcc == country).Any()

相关内容

  • 没有找到相关文章