Анализатор обнаружил, что результат LINQ метода с отложенным выполнением не исполняется.
Рассмотрим пример:
public static void PrintNames(List<string> names, char startLetter) { int it = 0; var filteredNames = names.Where(name => { ++it; Console.WriteLine($"{it}) {name}"); return name.StartsWith(startLetter); }); Console.WriteLine($"Type: '{filteredNames.GetType()}'"); Console.WriteLine(String.Join(',', names)); }
В метод Where
передаётся делегат, который, помимо условия фильтрации, выводит на консоль элементы и их позиции из исходной коллекции.
Однако ни вывода имён с позициями, ни фильтрации не произойдёт. В метод String.Join
вместо filteredNames
предаётся names
. По этой причине отфильтрованная коллекция не будет выведена на консоль. Более того, фильтрация в принципе не будет выполнена. Подобное поведение обусловлено тем, что при вызове Where
фильтрация выполняется не в момент вызова, а является отложенной. Следовательно, до тех пор, пока не будет произведено итерирование по коллекции, код делегата не выполнится.
Подробнее об отложенном выполнении можно узнать здесь.
Стоит отметить, что после вызова Where
с помощью метода GetType
выводится тип коллекции. При вызов данного метода не выполняется итерирование по коллекции, из чего следует, что делегат, переданный в Where
, также не отработает.
Для исправления в String.Join
нужно предавать не names
, а filteredNames
:
public static void PrintNames(List<string> names, char startLetter) { int it = 0; var filteredNames = names.Where(name => { ++it; Console.WriteLine($"{it}) {name}"); return name.StartsWith(startLetter); }); Console.WriteLine($"Type: '{filteredNames.GetType()}'"); Console.WriteLine(String.Join(',', filteredNames)); }
При вызове String.Join
будет выполнено итерирование по filteredNames
, что запустит фильтрацию коллекции. Следовательно, код делегата выполнится, и элементы с позициями будут выведены на консоль. Также на консоль выведется отфильтрованная коллекция.
Данная диагностика классифицируется как: