Это расширение вопроса от доступа к модифицированному закрытию . Я просто хочу проверить, действительно ли следующее достаточно безопасно для производственного использования.
List<string> lists = new List<string>();
//Code to retrieve lists from DB
foreach (string list in lists)
{
Button btn = new Button();
btn.Click += new EventHandler(delegate { MessageBox.Show(list); });
}
Я прохожу через это только один раз при запуске. Пока вроде работает нормально. Как упоминал Джон, в некоторых случаях результат может быть противоречивым. Так что мне нужно здесь остерегаться? Будет ли нормально, если список будет проходить более одного раза?
Ответы:
До C # 5 вам нужно было повторно объявить переменную внутри foreach - иначе она будет общей, и все ваши обработчики будут использовать последнюю строку:
Важно отметить, что, начиная с C # 5, это изменилось, и, в частности, в случае
foreach
, вам больше не нужно этого делать: код в вопросе будет работать, как ожидалось.Чтобы показать, что это не работает без этого изменения, примите во внимание следующее:
Выполните указанное выше до C # 5 , и хотя каждая кнопка имеет другое имя, нажатие на кнопки показывает «Wilma» четыре раза.
Это связано с тем, что спецификация языка (ECMA 334 v4, 15.8.4) (до C # 5) определяет:
Обратите внимание, что переменная
v
(вашаlist
) объявляется вне цикла. Таким образом, по правилам захваченных переменных, все итерации списка будут иметь общий держатель захваченной переменной.Начиная с C # 5, это изменено: переменная итерации (
v
) ограничена внутри цикла. У меня нет ссылки на спецификацию, но в основном она выглядит следующим образом:Повторная отмена подписки; если вы активно хотите отказаться от подписки на анонимный обработчик, уловка состоит в том, чтобы захватить сам обработчик:
Аналогично, если вам нужен однократный обработчик событий (например, Load и т. Д.):
Теперь это самоотписка ;-p
источник
for
в 5.0 не изменился