问题
I hope I worded the title of my question appropriately.
In c# I can use lambdas (as delegates), or the older delegate syntax to do this:
Func<string> fnHello = () => \"hello\";
Console.WriteLine(fnHello());
Func<string> fnHello2 = delegate()
{
return \"hello 2\";
};
Console.WriteLine(fnHello2());
So why can\'t I \"inline\" the lambda or the delegate body, and avoid capturing it in a named variable (making it anonymous)?
// Inline anonymous lambda not allowed
Console.WriteLine(
(() => \"hello inline lambda\")()
);
// Inline anonymous delegate not allowed
Console.WriteLine(
(delegate() { return \"hello inline delegate\"; })()
);
An example that works in javascript (just for comparison) is:
alert(
(function(){ return \"hello inline anonymous function from javascript\"; })()
);
Which produces the expected alert box.
UPDATE: It seems you can have an inline anonymous lambda in C#, if you cast appropriately, but the amount of ()\'s starts to make it unruly.
// Inline anonymous lambda with appropriate cast IS allowed
Console.WriteLine(
((Func<string>)(() => \"hello inline anonymous lambda\"))()
);
Perhaps the compiler can\'t infer the sig of the anonymous delegate to know which Console.WriteLine() you\'re trying to call? Does anyone know why this specific cast is required?
回答1:
Lambdas in C# do not have types, until they are used in a context that casts them to a delegate or Expression type. That's why you can't say
var x = () => "some lambda";
You might enjoy
http://blogs.msdn.com/ericlippert/archive/2007/01/11/lambda-expressions-vs-anonymous-methods-part-two.aspx
http://blogs.msdn.com/ericlippert/archive/2007/01/12/lambda-expressions-vs-anonymous-methods-part-three.aspx
回答2:
It seems to work if you give it a type cast:
String s = ((Func<String>) (() => "hello inline lambda"))();
Is it useless? Not entirely. Take the below:
String s;
{
Object o = MightBeNull();
s = o == null ? "Default value" : o.ToString();
}
Now consider this:
String S = ((Func<Object,String>)(o => o == null ? "Default value" : o.ToString())
)(MightBeNull());
It's a little ugly, but it is compact.
回答3:
When you write Func<string> = ...
, the compiler knows that it has to create an object of type Func<string>
. But when you write that delegate inline, the compiler doesn't know object of which type it has to create.
Having said the above, an obvious conclusion can be drawn: just tell the compiler the type explicitly!
Console.WriteLine( new Func<string>( () => "Hello" )() );
UPDATE
Ok, while I was writing the answer, you updated your post. I believe my answer above already answers the question "why this specific type is required". To reiterate: because the compiler doesn't know object of which type to create.
Now to elaborate a bit on the "the compiler can't infer the sig of the anonymous delegate" part. You see, it's not like in JavaScript. In C#, there's no generic "function" (or "method") type. Each delegate must have an explicitly specified signature and type name. And when you're creating a delegate, the compiler must know what type.
Now, I can see how you may imply that the compiler could just construct a delegate type on the fly, like it does with anonymous object types (aka new { a = 1, b = "xyz" }
). But think about it for a moment: there would be probably no use for such delegate anyway. I mean, you can't pass it to another method, because that method has to declare types of it's arguments first. And you can make an event out of it, because, again, you must have a named type.
Something like that...
回答4:
You can use inline lambda expressions for methods that take in a Delegate parameter.
However there is a slight catch - if the parameter is typed as the base Delegate type, you'd need to explicitly cast it to a specific derivation of Delegate (say Action) ; else the compiler would complain.
Similar questions:
Anonymous method in Invoke call
Anonymous methods and delegates
来源:https://stackoverflow.com/questions/2687942/why-cant-c-sharp-use-inline-anonymous-lambdas-or-delegates