PVS-Studio.com logo
>
>
>
V3220. The result of the LINQ method wi…


V3220. The result of the LINQ method with deferred execution is never used. The method will not be executed.

Анализатор обнаружил, что результат 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, что запустит фильтрацию коллекции. Следовательно, код делегата выполнится, и элементы с позициями будут выведены на консоль. Также на консоль выведется отфильтрованная коллекция.

Данная диагностика классифицируется как: