Why can't c# use inline anonymous lambdas or delegates?

20,068

Solution 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

Solution 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.

Solution 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...

Solution 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

Share:
20,068
Samuel Meacham
Author by

Samuel Meacham

I'm Samuel Meacham, a database, web and .NET (C#) developer. I was an advanced TSQL developer at Chase Bank for many years, where I honed and hardened my database skills. I left Chase for CB Richard Ellis in 2007, and I work in their commercial Mapping Center, where I work with an amazing development team. We're very lucky to work for a company that always gives us the latest tools, fast hardware, a great environment, and the flexibility to solve problems as we see fit. I've been programming since I was 14, and I still can't get enough of it.

Updated on May 30, 2020

Comments

  • Samuel Meacham
    Samuel Meacham almost 4 years

    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?