Перебор списка и использование объектов внутри анонимной функции - PullRequest
0 голосов
/ 04 апреля 2011

У меня есть List<string>, и я хочу перебрать эту коллекцию и что-то сделать с каждой строкой при нажатии кнопки. У меня есть небольшой пример, чтобы проиллюстрировать, что я пытаюсь сделать:

//items is a System.Collections.Generic.List<string>
foreach (string s in items)
{
    Button b = new Button() { Content = s };
    b.Click += (obj, ev) =>
    {
        MessageBox.Show(s);
    }
    //add b to form, container, etc...
}

Как и следовало ожидать, кнопки создаются соответствующим образом с правильным содержанием, однако, когда я нажимаю любую из кнопок, текст внутри MessageBox всегда является последней строкой в ​​items. Чего мне не хватает с этим? Почему все функции Click для кнопок передаются последнему элементу в коллекции?

1 Ответ

8 голосов
/ 04 апреля 2011

Меняется foreach цикл s, который используется в лямбда-выражении.Лямбда использует текущее значение s в точке исполнения, не объявляя его (в techspeak: «замыкания закрываются по переменным, а не по значениям»).Вам нужно будет создать локальную переменную:

foreach (string s in items)
{
    string local = s;
    Button b = new Button() { Content = s };
    b.Click += (obj, ev) =>
    {
        MessageBox.Show(local);
    }
    //add b to form, container, etc...
}

Таким образом, у вас есть ссылка на экземпляр s в точке декларации, а не выполнения.

Эрик Липперт имеет двафантастические статьи об этом: часть 1 , часть 2 .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...