# V3219. The variable was changed after it was captured in a LINQ method with deferred execution. The original value will not be used when the method is executed.

Анализатор обнаружил изменение захваченной переменной, которая использовалась в LINQ методе с отложенным выполнением. При таком сценарии изначальное значение переменной не будет учитываться.

Рассмотрим пример:

    private static List<string> _names = new() { "Tucker", "Bob", "David" };

    public static void ProcessNames()
    {
      string startLetter = "T";
      var names = _names.Where(c => !c.StartsWith(startLetter));

      startLetter = "B";
      names = names.Where(c => !c.StartsWith(startLetter))
                   .ToList();
    }

В методе `ProcessNames` производится фильтрация имён по первой букве. Ожидается, что в результате переменная `names` будет содержать имена, не начинающиеся на `T` и `B`. Однако поведение программы будет иным. При выполнении этого метода в `names` будет коллекция, состоящая из `Tucker` и `David`.

Подобное поведение обусловлено тем, что при вызове `Where` фильтрация выполняется не в момент вызова, а является отложенной. Так как между двумя вызовами `Where` переменной `startLetter` присваивается `B`, значение `T` не учитывается при итоговом вычислении.

Это происходит из-за того, что `startLetter` захвачена при первом вызове `Where`, и её значение изменилось перед вторым вызовом `Where`. Как следствие, будет получена коллекция, которая фильтруется только по `B`.

Подробнее об отложенном выполнении можно узнать здесь.

Чтобы метод работал корректно, нужно либо немедленно выполнить запрос (первый `Where`) и работать с результатом выполнения, либо использовать другую переменную в лямбда-выражении второго `Where`.

Рассмотрим первый сценарий:

    private static List<string> _names = new() { "Tucker", "Bob", "David" };

    public static void ProcessNames()
    {
      string startLetter = "T";
      var names = _names.Where(c => !c.StartsWith(startLetter))
                        .ToList();

      startLetter = "B";
      names = names.Where(c => !c.StartsWith(startLetter))
                   .ToList();
    }

После первого метода `Where` вызывается `ToList`, при выполнении которого создаётся коллекция, отфильтрованная с помощью первого `Where`. На момент изменения захваченной переменной коллекция уже сформирована, следовательно, фильтрация будет выполняться корректно.

Рассмотрим второй вариант исправления:

    private static List<string> _names = new() { "Tucker", "Bob", "David" };

    public static void ProcessNames()
    {
      string startLetter1 = "T";
      var names = _names.Where(c => !c.StartsWith(startLetter1));

      string startLetter2 = "B";
      names = names.Where(c => !c.StartsWith(startLetter2))
                   .ToList();
    }

В данном случае захваченной переменной не присваивается новое значение между вызовами `Where`, вместо этого используется переменная `startLetter2`. В результате фильтрация отработает корректно.

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V3219.