Последняя функция захвачена вашей лямбдой (ее закрытием). Вы должны создать локальную переменную для захвата функции на каждой итерации:
foreach (Feature feature in features) {
Feature current = feature;
sscce.Click += (object sender, EventArgs e) => { current.doIt(); };
}
Я предлагаю вам прочитать Closing over the loop variable статью в блоге Эрика Липперта.
ПРИМЕЧАНИЕ: Это было зафиксировано в последней версии C#
Чтобы понять, что происходит, давайте посмотрим, что код генерируется в вашем случае (до C# 5). Таким образом, ваш лямбда использует локальную переменную, это не достаточно, чтобы сгенерировать метод - компилятор генерирует частный класс, который улавливает локальные переменные, используемые в лямбда:
private sealed class AnonymousClass
{
public Feature feature;
public void AnonymousMethod(object sender, EventArgs e)
{
this.feature.doIt();
}
}
И ваш код изменен так, что он использует экземпляр этого AnonymousClass и выписывает это AnonymousMethod чтобы Нажмите событие:
using(var enumerator = ((IEnumerable<Feature>)features).GetEnumerator())
{
AnonymousClass x = new AnonymousClass();
while(enumerator.MoveNext())
{
x.feature = (Feature)enumerator.Current;
sscce.Click += new EventHandler(x.AnonymousMethod);
}
}
Как вы можете видеть, вы подписались AnonymousMethod того же экземпляра AnonymousClass несколько раз. И этот экземпляр будет иметь функцию, равную последней назначенной функции. Теперь то, что изменяется при копировании текущей функции в локальной переменной:
using(var enumerator = ((IEnumerable<Feature>)features).GetEnumerator())
{
while(enumerator.MoveNext())
{
AnonymousClass x = new AnonymousClass();
x.current = (Feature)enumerator.Current; // field has local variable name
sscce.Click += new EventHandler(x.AnonymousMethod);
}
}
В этом случае AnonymousClass экземпляр, созданный на каждой итерации, таким образом, AnonymousMethods различных экземпляров класса (каждый с собственной функцией захваченном) будет обрабатывать событие Click. Почему код отличается - потому что, как говорит Эрик, закрытие (т. Е. Анонимный класс) закрывается над переменными. Чтобы быть закрытым по локальной переменной в теле цикла, во втором случае экземпляр анонимного класса должен быть создан внутри цикла.
Какую версию C# вы используете? –
Я использую Microsoft Visual C# 2010, где компилятор? Что это за имя? – Aerospace
У Jon Skeet есть полезная страница. Короче говоря, вы, вероятно, используете C# 4.0 или ранее: http://csharpindepth.com/Articles/Chapter1/Versions.aspx Это исправление не было введено до тех пор, пока C# 5. –