delegate keyword vs. lambda notation


Question

Once it is compiled, is there a difference between:

delegate { x = 0; }

and

() => { x = 0 }

?

1
175
10/7/2011 12:18:45 PM

Accepted Answer

Short answer : no.

Longer answer that may not be relevant:

  • If you assign the lambda to a delegate type (such as Func or Action) you'll get an anonymous delegate.
  • If you assign the lambda to an Expression type, you'll get an expression tree instead of a anonymous delegate. The expression tree can then be compiled to an anonymous delegate.

Edit: Here's some links for Expressions.

  • System.Linq.Expression.Expression(TDelegate) (start here).
  • Linq in-memory with delegates (such as System.Func) uses System.Linq.Enumerable. Linq to SQL (and anything else) with expressions uses System.Linq.Queryable. Check out the parameters on those methods.
  • An Explanation from ScottGu. In a nutshell, Linq in-memory will produce some anonymous methods to resolve your query. Linq to SQL will produce an expression tree that represents the query and then translate that tree into T-SQL. Linq to Entities will produce an expression tree that represents the query and then translate that tree into platform appropriate SQL.
137
6/26/2015 12:39:57 PM

I like David's answer, but I thought I'd be pedantic. The question says, "Once it is compiled" - which suggests that both expressions have been compiled. How could they both compile, but with one being converted to a delegate and one to an expression tree? It's a tricky one - you have to use another feature of anonymous methods; the only one which isn't shared by lambda expressions. If you specify an anonymous method without specifying a parameter list at all it is compatible with any delegate type returning void and without any out parameters. Armed with this knowledge, we should be able to construct two overloads to make the expressions completely unambiguous but very different.

But disaster strikes! At least with C# 3.0, you can't convert a lambda expression with a block body into an expression - nor can you convert a lambda expression with an assignment in the body (even if it is used as the return value). This may change with C# 4.0 and .NET 4.0, which allow more to be expressed in an expression tree. So in other words, with the examples MojoFilter happened to give, the two will almost always be converted to the same thing. (More details in a minute.)

We can use the delegate parameters trick if we change the bodies a little bit though:

using System;
using System.Linq.Expressions;

public class Test
{
    static void Main()
    {
        int x = 0;
        Foo( () => x );
        Foo( delegate { return x; } );
    }

    static void Foo(Func<int, int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }

    static void Foo(Expression<Func<int>> func)
    {
        Console.WriteLine("I suspect the lambda expression...");
    }
}

But wait! We can differentiate between the two even without using expression trees, if we're cunning enough. The example below uses the overload resolution rules (and the anonymous delegate matching trick)...

using System;
using System.Linq.Expressions;

public class Base
{
    public void Foo(Action action)
    {
        Console.WriteLine("I suspect the lambda expression...");
    }
}

public class Derived : Base
{
    public void Foo(Action<int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }
}

class Test
{
    static void Main()
    {
        Derived d = new Derived();
        int x = 0;
        d.Foo( () => { x = 0; } );
        d.Foo( delegate { x = 0; } );
    }
}

Ouch. Remember kids, every time you overload a method inherited from a base class, a little kitten starts crying.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon