W poniższym programie, DummyMethod zawsze drukuje 5. Ale jeśli użyjemy skomentowanego kodu, otrzymamy różne wartości (tj. 1, 2, 3, 4). Czy ktokolwiek może wyjaśnić, dlaczego tak się dzieje?Problem z delegatami w C#
delegate int Methodx(object obj);
static int DummyMethod(int i)
{
Console.WriteLine("In DummyMethod method i = " + i);
return i + 10;
}
static void Main(string[] args)
{
List<Methodx> methods = new List<Methodx>();
for (int i = 0; i < 5; ++i)
{
methods.Add(delegate(object obj) { return DummyMethod(i); });
}
//methods.Add(delegate(object obj) { return DummyMethod(1); });
//methods.Add(delegate(object obj) { return DummyMethod(2); });
//methods.Add(delegate(object obj) { return DummyMethod(3); });
//methods.Add(delegate(object obj) { return DummyMethod(4); });
foreach (var method in methods)
{
int c = method(null);
Console.WriteLine("In main method c = " + c);
}
}
Również jeśli poniższy kod zostanie użyty, otrzymam pożądany wynik.
for (int i = 0; i < 5; ++i)
{
int j = i;
methods.Add(delegate(object obj) { return DummyMethod(j); });
}
Favouriting this question. Takie zachowanie jest po prostu "niebezpieczne". Założę się, że pojawią się one częściej jako jeden z tych trudnych do debugowania problemów, ponieważ C# porusza się coraz bardziej w kierunku zorientowanego na delegata sposobu zachowywania się w kapsule. Jest to podobne do zapętlonego odpowiednika klauzul przełączających, które mogą kaskadować w dół bez obowiązkowego "przerwania"; klauzula –
@Neil: Zgadzam się, że to gorący punkt. Jest to bardziej zagmatwane, gdy jest postrzegane z "foreach" - tak bardzo, że zespół C# rozważa zmianę zachowania dla tej sprawy. (Trudno wyobrazić sobie scenariusz, w którym zachowanie foreach jest pożądane, sytuacja pętli for jest bardziej zrozumiała, ponieważ jasne jest, że zmienna jest zadeklarowana tylko raz.) –
możliwy duplikat [C# przechwyconej zmiennej pętli] (http: //stackoverflow.com/questions/271440/c-sharp-captured-variable-in-loop) – nawfal