Reputation: 778
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
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
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
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
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