bunglestink
bunglestink

Reputation: 778

Invoking Lambdas at Creation

In javascript, it is common to use closures and create then immediately invoke an anonymous function, as below:

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

Due to strong typing, this very verbose in C#:

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

Is there a more elegant way to go about this type of thing in C#?

Upvotes: 7

Views: 188

Answers (4)

CodesInChaos
CodesInChaos

Reputation: 108840

You don't need the outer lambda in C#, it can be replaced by a simple block.

Directly invoking a lambda is a workaround for the lack of block level variables in Javascript (new versions support block scope using let).

Func<int> counter;

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

Upvotes: 14

Dave Rael
Dave Rael

Reputation: 1759

is the cast really necessary? it depends on how you are using the func.

could simply do something like

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

this seems a little strange, though, declaring the variable inside the func and i'm pretty sure it's not really what you intend.

Upvotes: -1

Richard Anthony Hein
Richard Anthony Hein

Reputation: 10650

There's not a much nicer way, but the cast is a bit confusing, so I'd prefer this:

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

Edit: As CodeInChaos just asked, the outer lambda seems redundant.

Edit 2: No, it's not redundant because you want a closure over n. So either the way above or:

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

Edit 3: Since I am not sure if you want to reuse the counter function, such that it can be reinitialized, which of the two scenarios (or another scenario) do you want:

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

Output: Counter0: 0 1 2 3 4 0 1 2 3 4 Counter1: 0 1 2 3 4 5 6 7 8 9

Upvotes: 1

George Duckett
George Duckett

Reputation: 32438

The only thing I can suggest is Func<int> counter could be var counter, but can't think of anything else. Note that counter is still strongly-typed.


See also: var

Upvotes: 1

Related Questions