Вызов лямбд при создании - PullRequest
7 голосов
/ 24 ноября 2011

В javascript принято использовать замыкания и создавать, а затем немедленно вызывать анонимную функцию, как показано ниже:

var counter = (function() {
    var n = 0;
    return function() { return n++; }
}());

Из-за строгой типизации это очень многословно в C #:

Func<int> counter = ((Func<Func<int>>)(() =>
{
    int n = 0;
    return () => n++;
}))();

Есть ли более элегантный способ сделать что-то подобное в C #?

Ответы [ 4 ]

15 голосов
/ 24 ноября 2011

Вам не нужна внешняя лямбда в C #, ее можно заменить простым блоком.

Непосредственный вызов лямбды - это обходной путь для отсутствия переменных уровня блока в Javascript (новые версии поддерживают область блока, используя let).

Func<int> counter;

{
     int n = 0;
     counter = () => n++;
}
1 голос
/ 24 ноября 2011

Нет более приятного способа, но состав немного сбивает с толку, поэтому я бы предпочел следующее:

Func<int> counter = new Func<Func<int>>(() => { var n = 0; return () => n++; })();

Редактировать: Как только что спросил CodeInChaos, внешняя лямбда выглядит избыточной.

Редактировать 2: Нет, это не избыточно, потому что вы хотите замыкание над n. Так что либо выше, либо:

Func<Func<int>> counter = () => { var n = 0; return () => n++; };
int x = counter()();

Редактировать 3: Поскольку я не уверен, хотите ли вы повторно использовать функцию счетчика, чтобы ее можно было повторно инициализировать, какой из двух сценариев (или другой сценарий) вы хотите:

            Func<Func<int>> counter0 = () => { var n = 0; return () => n++; };

        Console.WriteLine("Counter0:");
        var count0 = counter0();
        for (var i = 0; i < 5; i++)
        {
            Console.WriteLine(count0());
        }

        var count1 = counter0();
        for (var i = 0; i < 5; i++)
        {

            Console.WriteLine(count1());
        }

        Console.WriteLine("Counter1:");
        Func<int> counter1 = new Func<Func<int>>(() => { var n = 0; return () => n++; })();

        for (var i = 0; i < 5; i++)
        {
            Console.WriteLine(counter1());
        }

        for (var i = 0; i < 5; i++)
        {
            Console.WriteLine(counter1());
        }

Выход: Counter0: 0 1 2 3 4 0 1 2 3 4 Counter1: 0 1 2 3 4 5 6 7 8 9

1 голос
/ 24 ноября 2011

Единственное, что я могу предложить, это Func<int> counter, может быть var counter, но больше ничего не могу придумать. Обратите внимание, что counter все еще строго напечатан.


См. Также: var

0 голосов
/ 24 ноября 2011

действительно ли необходим актерский состав? это зависит от того, как вы используете функцию.

может просто сделать что-то вроде

Func<int> counter = () => { int n; return n++;}

это кажется немного странным, объявляя переменную внутри функции, и я уверен, что это не совсем то, что вы намереваетесь.

...