Como dizer uma function lambda para capturar uma cópia em vez de uma referência em c #?

Eu tenho aprendido C # e estou tentando entender lambdas. Neste exemplo abaixo, imprime 10 dez vezes.

class Program { delegate void Action(); static void Main(string[] args) { List actions = new List(); for (int i = 0; i Console.WriteLine(i)); foreach (Action a in actions) a(); } } 

Obviamente, a class gerada por trás do lambda está armazenando uma referência ou ponteiro para a variável int i e está atribuindo um novo valor à mesma referência sempre que o loop for iterado. Existe uma maneira de forçar o lamda para pegar uma cópia em vez disso, como a syntax C ++ 0x

 [&](){ ... } // Capture by reference 

vs.

 [=](){ ... } // Capture copies 

O que o compilador está fazendo é puxar seu lambda e quaisquer variables ​​capturadas pelo lambda em uma class aninhada gerada pelo compilador.

Após a compilation, seu exemplo se parece muito com isso:

 class Program { delegate void Action(); static void Main(string[] args) { List actions = new List(); DisplayClass1 displayClass1 = new DisplayClass1(); for (displayClass1.i = 0; displayClass1.i < 10; ++displayClass1.i ) actions.Add(new Action(displayClass1.Lambda)); foreach (Action a in actions) a(); } class DisplayClass1 { int i; void Lambda() { Console.WriteLine(i); } } } 

Ao fazer uma cópia dentro do loop for, o compilador gera novos objects em cada iteração, da seguinte forma:

 for (int i = 0; i < 10; ++i) { DisplayClass1 displayClass1 = new DisplayClass1(); displayClass1.i = i; actions.Add(new Action(displayClass1.Lambda)); } 

A única solução que consegui encontrar é criar uma cópia local primeiro:

 for (int i = 0; i < 10; ++i) { int copy = i; actions.Add(() => Console.WriteLine(copy)); } 

Mas estou tendo problemas para entender por que colocar uma cópia dentro do for-loop é diferente de ter a captura de lambda i .

A única solução é fazer uma cópia local e referenciar isso dentro do lambda. Todas as variables ​​em C # (e VB.Net) quando acessadas em um fechamento terão semântica de referência versus semântica de cópia / valor. Não há como alterar esse comportamento em nenhum dos idiomas.

Nota: Na verdade, ele não compila como referência. O compilador eleva a variável para uma class de fechamento e redireciona os accesss de “i” para um campo “i” dentro da class de fechamento especificada. Muitas vezes, é mais fácil pensar nisso como semântica de referência.

Lembre-se que expressões lambda são realmente apenas açúcar sintático para methods anônimos.

Dito isto, o que você está realmente procurando é como os methods anônimos usam variables ​​locais em um escopo pai.

Aqui está um link descrevendo isso. http://www.codeproject.com/KB/cs/InsideAnonymousMethods.aspx#4