Ответ 1
Причиной предупреждения является то, что внутри цикла вы можете получить доступ к переменной, которая меняется. Тем не менее, "fix" на самом деле ничего не делает для вас в этом контексте без цикла.
Представьте, что у вас был цикл FOR, и внутри него было if, а объявление строки было вне него. В этом случае ошибка будет правильно идентифицировать проблему захвата ссылки на что-то нестабильное.
Пример того, чего вы не хотите:
string acctStatus
foreach(...)
{
acctStatus = account.AccountStatus[...].ToString();
if (!SettableStatuses().Any(status => status == acctStatus))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
}
Проблема в том, что замыкание будет захватывать ссылку на acctStatus, но каждая итерация цикла изменит это значение. В этом случае было бы лучше:
foreach(...)
{
string acctStatus = account.AccountStatus[...].ToString();
if (!SettableStatuses().Any(status => status == acctStatus))
acctStatus = ACCOUNTSTATUS.Pending.ToString();
}
Поскольку переменный контекст представляет собой цикл, новый экземпляр будет создаваться каждый раз, потому что мы переместили переменную внутри локального контекста (цикл for).
Рекомендация звучит как ошибка в анализе Resharper этого кода. Однако во многих случаях это является серьезной проблемой (например, первый пример, когда ссылка меняется, несмотря на ее захват в закрытии).
Мое эмпирическое правило, когда есть сомнения, делает локальный.
Вот пример реального мира, в котором я был укушен:
menu.MenuItems.Clear();
HistoryItem[] crumbs = policyTree.Crumbs.GetCrumbs(nodeType);
for (int i = crumbs.Length - 1; i > -1; i--) //Run through items backwards.
{
HistoryItem crumb = crumbs[i];
NodeType type = nodeType; //Local to capture type.
MenuItem menuItem = new MenuItem(crumb.MenuText);
menuItem.Click += (s, e) => NavigateToRecord(crumb.ItemGuid, type);
menu.MenuItems.Add(menuItem);
}
Обратите внимание, что я фиксирую тип NodeType local, note nodeType и HistoryItem crumb.ItemGuid, а не крошки [i].ItemGuid. Это гарантирует, что у моего закрытия не будет ссылок на элементы, которые будут меняться.
До использования локалей события будут запускаться с текущими значениями, а не с захваченными значениями, которые я ожидал.