Reputation: 36654
I have wrote the following code:
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 shows me a warning:
Possible duplicate enumeration of IEnumerable
What does this mean? Why is this a warning?
Upvotes: 6
Views: 414
Reputation: 47038
It means that you might calculate the content of the IEnumerable
twice (or more). If this is expensive, like calling a database this is bad for performance. If the underlying source is a List<T>
and there is a simple projection or something else non-expensive this is not a problem.
You could of course rewrite the expression to use the enumerables only once.
!blackListCountriesCodes.Contains(Consts.ALL.ToString())
&& !blackListCountriesCodes.Contains(country)
could be rewritten as
!blackListCountriesCodes
.Where(blcc => blcc == Consts.ALL.ToString() || blcc == country).Any()
Upvotes: 1
Reputation: 726599
This means that your code may enumerate the blackListCountriesCodes
and whiteListCountriesCodes
several times. Since LINQ uses deferred evaluation, this may cause slowness, especially when the pair
has lots of data, and Where
clauses are complex (it does not look like any of that applies in your situation, though).
You can eliminate the warning (and the alleged slowness) by "materializing" the enumerations into lists, like this:
var blackListCountriesCodes =
pair.Criterion.CountriesExceptions.Select(countryItem => countryItem.CountryCode).ToList();
var whiteListCountriesCodes =
pair.Criterion.Countries.Select(countryItem => countryItem.CountryCode).ToList();
Upvotes: 1
Reputation: 245429
LINQ Queries defer their execution until you do something with the results. In this case, calling Contains()
twice on the same collection could cause the results to be enumerated twice which, depending on the query, could cause performance issues.
You can solve this by simply tacking a ToList()
call on the end of your query which will force execution of the query and store the results a single time.
Upvotes: 9