Замыкания для анонимных методов в C # 3.0 - PullRequest
2 голосов
/ 11 июня 2009

Почему существуют замыкания для анонимных методов? Почему бы просто не передать состояние в метод без дополнительных затрат на создание нового класса с копированием переменных закрытия? Разве это не просто возврат к «созданию всего глобального»?

Кто-то уговаривает меня, я чувствую, что что-то здесь упускаю ...

Ответы [ 6 ]

8 голосов
/ 11 июня 2009

Чисто, удобство ... вы не знаете, какое состояние вам понадобится при определении, например, Predicate<T> - рассмотрите:

List<int> data = new List<int> {1,2,3,4,5,6,7,8,9,10};
int min = int.Parse(Console.ReadLine()), max = int.Parse(Console.ReadLine());
List<int> filtered = data.FindAll(i => i >= min && i <= max);

здесь мы передали два дополнительных бита состояния в Predicate<T> (min и max) - но мы не можем определить List<T>.FindAll(Predicate<T>), чтобы знать об этом, поскольку это деталь вызывающего абонента.

Альтернатива - писать сами классы, но это сложно, даже если мы ленивы:

class Finder {
    public int min, max;
    public bool CheckItem(int i) { return i >= min && i <= max;}
}
...
Finder finder = new Finder();
finder.min = int.Parse(Console.ReadLine());
finder.max = int.Parse(Console.ReadLine());
List<int> filtered = data.FindAll(finder.CheckItem);

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

Подумайте также, как часто вы используете такие конструкции, особенно для таких вещей, как LINQ: вам не хотелось бы делать это каким-либо другим способом ...

3 голосов
/ 11 июня 2009

Возможно, вам не о чем беспокоиться о создании нового класса. Это просто удобный способ для CLR сделать связанные переменные (захваченные замыканием) доступными в куче. Они по-прежнему доступны только в рамках замыкания, поэтому они вовсе не являются «глобальными» в традиционном смысле.

Я полагаю, что причиной их существования является в основном удобство для программиста. На самом деле, это чисто то, что касается меня. Вы могли бы эмулировать поведение замыкания до того, как оно появилось в C #, но вы не получите ничего из того, что предлагает C # 3.0. Весь смысл замыканий в том, что вам не нужно передавать переменные в родительской области в функцию , потому что они автоматически связаны. Программисту намного проще и понятнее работать, если учесть, что альтернатива - это true глобальные переменные.

0 голосов
/ 11 июня 2009

Некоторые методы требуют определенной подписи. Например:

public void set_name_on_click(string name)
{
    button.Click += (s,e) => { button.Text = name; };
}

Полное закрытие решает это очень аккуратно. Вы действительно не хотите связываться с подписью анонимных методов.

0 голосов
/ 11 июня 2009

Потому что вы берете, напишите это:

var divsor = [...]
for(int x = 0; x < 10000000; x++){
     source[x] = source[x] / divsor         
}

И легко превратить это в

var divsor = [...]
Parallel.For(int x = 0; x < 10000000; x++, ()=> {
     source[x] = source[x] / divsor         
})
0 голосов
/ 11 июня 2009

По крайней мере, одна мысль состоит в том, что замыкания существуют в других языках, таких как javascript. Таким образом, они, вероятно, включили замыкания, чтобы соответствовать предыдущему опыту людей с анонимными методами.

0 голосов
/ 11 июня 2009

Поскольку CLR позаботится об этом, самый простой способ «передать состояние в метод» - это автоматически сгенерировать класс, который инкапсулирует это состояние.

...