﻿# 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 методе с отложенным выполнением\. При таком сценарии изначальное значение переменной не будет учитываться\.

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

```cpp
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`\.

Подробнее об отложенном выполнении можно узнать [здесь](https://learn.microsoft.com/en-us/dotnet/csharp/linq/get-started/introduction-to-linq-queries)\.

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

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

```cpp
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`\. На момент изменения захваченной переменной коллекция уже сформирована, следовательно, фильтрация будет выполняться корректно\.

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

```cpp
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`\. В результате фильтрация отработает корректно\.