Как определить функцию lambda для копирования копии вместо ссылки на C #?

Я изучаю C #, и я пытаюсь понять lambda. В этом примере ниже он распечатывается 10 десять раз.

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(); } } 

Очевидно, сгенерированный class за лямбдой хранит ссылку или указатель на переменную int i и присваивает новое значение той же ссылке каждый раз, когда цикл итерации. Есть ли способ заставить lamda захватить копию вместо этого, как синтаксис C ++ 0x

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

против

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

Что делает компилятор, это тянуть вашу лямбду и любые переменные, захваченные лямбдой, в генерируемый компилятором вложенный class.

После компиляции ваш пример выглядит примерно так:

 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); } } } 

Сделав копию в цикле for, компилятор генерирует новые объекты на каждой итерации, например:

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

Единственное решение, которое я смог найти, – сначала сделать локальную копию:

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

Но у меня возникли проблемы с пониманием того, почему размещение копии внутри цикла for-loop отличается от наличия lambda-захвата i .

Единственное решение – сделать локальную копию и ссылку, которая находится внутри lambda. Все переменные в C # (и VB.Net) при доступе в закрытии будут иметь семантику ссылок и семантику копирования / значения. Невозможно изменить это поведение на любом языке.

Примечание. На самом деле это не компиляция в качестве ссылки. Компилятор подталкивает переменную в class замыкания и перенаправляет обращения «i» в поле «i» внутри данного classа замыкания. Часто легче думать об этом как о контрольной семантике.

Помните, что lambda-выражения на самом деле являются только синтаксическим сахаром для анонимных методов.

При этом то, что вы действительно ищете, – это то, как анонимные методы используют локальные переменные в родительской области.

Вот ссылка, описывающая это. http://www.codeproject.com/KB/cs/InsideAnonymousMethods.aspx#4

Interesting Posts

Как остановить анимацию в C # / WPF?

Почему моя беспроводная сетевая карта должна быть сброшена каждый раз, когда я запускаю или разбужу свою машину?

Защита форматирования в Excel 2007

Обновление до Windows 7 Rolls Back to Vista

Специальная сериализация Jackson JSON для определенных полей

В чем разница между «system32 \ java.exe» и «Program Files \ Java \ jdk1.6.0_33 \ bin \ java.exe»?

Требования к минимальной автономной графической карте для двух мониторов

Как изменить цвет фона экспорта Inkscape по умолчанию с желтого на белый?

Android Deep linking: используйте ту же ссылку для приложения и магазина воспроизведения

Ярлык клавиатуры для отображения или снятия с экрана окна в OS X

Windows 7 застрял на CLASSPNP.SYS

Как мне перейти на подключенный сетевой диск в командной строке?

Как правильно использовать Google Plus для входа в систему с несколькими действиями?

Как установить плагины в редактор Sublime Text 2?

Excel: удалить только буквенные символы (сохранить специальные символы)

Давайте будем гением компьютера.