Understanding Lambda expressions and delegates [closed]
Asked Answered
O

6

15

I have been trying to figure this out for quite sometime (reading online blogs and articlaes), but so far unsuccessful.

What are delegates? What are Lambda Expressions? Advantages and disadvantages of both? Possible best practice of when to use one or the other?

Thanks in advance.

Overweigh answered 19/7, 2010 at 14:43 Comment(5)
possible duplicate of C#: delegate keyword vs. lambda notationGuadiana
Randolpho, thats not a duplicate of this question. I am looking for an understanding at a basic level of what is a Lambda Expression and a delegate.Overweigh
@Randolpho: not necessarily a dup here. I think the biggest part of OP's question is in asking what they are, whereas the question you're referring to is only concerned with the distinctions between the two.Blackboard
While not a duplicate, this is quite a broad question. Lambda expression and delegate are not very related. Better you could break it into two. See c-sharp-lambda-expression-why-should-i-use-this and delegates-in-c-sharp.Germano
Also this, this, this etc for some equivalent comparisons. Or may be all in one togetherGermano
S
30

Delegates are methods that you can use as variables, like strings etc. For example you can declare a delegate method with one argument:

delegate void OneArgumentDelegate(string argument);

It doesn't do anything, much like an interface. If you have a method in any class with one argument like this:

void SomeMethod(string someArgument) {}

It matches the signature of the delegate, and thus can be assigned to a variable of its type:

OneArgumentDelegate ThisIsAVariable = new OneArgumentDelegate(SomeMethod);
OneArgumentDelegate ThisIsAlsoAVariable = SomeMethod; // Shorthand works too

These can then be passed as arguments to methods and invoked, like so:

void Main()
{
  DoStuff(PrintString);
}

void PrintString(string text)
{
  Console.WriteLine(text);
}

void DoStuff(OneArgumentDelegate action) 
{
  action("Hello!");
}

This will output Hello!.

Lambda expressions are a shorthand for the DoStuff(PrintString) so you don't have to create a method for every delegate variable you're going to use. You 'create' a temporary method that's passed on to the method. It works like this:

DoStuff(string text => Console.WriteLine(text)); // single line
DoStuff(string text => // multi line
{
  Console.WriteLine(text);
  Console.WriteLine(text);
});

Lambda expressions are just a shorthand, you might as well create a seperate method and pass it on. I hope you understand it better now ;-)

Sloth answered 19/7, 2010 at 14:57 Comment(6)
It is unnecessary in most cases to declare the type of the input variable in the lambda expression, and IMO, makes code necessarily verbose (something the lambda expression was trying to solve in the first place. DoStuff(txt => Console.WriteLine(txt)) is equally sufficient.Krug
+1 A decent explanation - certainly better than most I have seen on-line.Bernardabernardi
@Krug I thought about leaving it out but decided against it for clarity. Leaving it out here could've confused people that aren't familiar with the syntax. In 'real' code, I usually leave it out though, as you suggest.Sloth
to say that lambda is shorthand for DoStuff(PrintString) might be unfortunate in the choice of examples though. Consider that DoStuff(text => Console.WriteLine(text)); is only a more verbose way of writing DoStuff(Console.WriteLine); since your lambda has the exact same signature as Console.WriteLine: they are both a method that takes a string and return nothing.Blackboard
@David You're right, of course, but I didn't want to use any complex examples in this. Could've done better, sure, but for the purpose I think this will do.Sloth
To get the lamda expression to work (VS 2017) I needed to delete string as per @DavidHedlund 's comment...Droshky
D
7

Delegate is an object that hold a reference to a function. Several different delegates may point to the same function. A delegate's type defines the footprint of a function it may point to.

Lambda expression is a function that doesn't have name. The only way to execute this function is to have a delegate pointing to the function. Lambda expressions are usually defined in place where you need a delegate to a function with a given footprint. This is useful to make code less verbose and at the same time more descriptive and flexible

I would suggest that you use a named function and a delegate to it whenever you have some code that is going to be called from different places. A common example is an event listener that you want to attach to several event producers.

Another point to consider writing a separate function is the complexity of the code. It isn't going to help anyone if you write a whole program inside a lambda expression.

On the other hand, you often need some trivial processing that you want to be executed in a callback manner. This is the point where you might love the lambda expressions.

What is very nice about lambda expressions that they inherit the scope they were defined in, so that you can easily your variables inside the lambda expression, and thus pass a lot of info inside. You should be careful though, see the Remarks section of this article.

Labdas are brilliant in conjunction with LINQ.

To conclude, I have to quote yet another must-read msdn section:

When you use method-based syntax to call the Where method in the Enumerable class (as you do in LINQ to Objects and LINQ to XML) the parameter is a delegate type System.Func. A lambda expression is the most convenient way to create that delegate. When you call the same method in, for example, the System.Linq.Queryable class (as you do in LINQ to SQL) then the parameter type is an System.Linq.Expressions.Expression where Func is any Func delegates with up to sixteen input parameters. Again, a lambda expression is just a very concise way to construct that expression tree. The lambdas allow the Where calls to look similar although in fact the type of object created from the lambda is different.
Drennen answered 19/7, 2010 at 14:51 Comment(1)
thanks for the info. Can you provide examples of when you would use a delegate and when you would use a Lambda Expression?Overweigh
A
5

No one has mentioned anonymous delegates. You can create delegates on the fly, without declaring them:

public void Action(Func<int, int> func);
...
Action(delegate(int x) { return x*x; });

Which is just a more verbose version of the lambda syntax:

Action(x => x*x);

Also note that the lambda syntax has more aggressive type inference. Another difference is that the lambda notation can be used to declare expression trees:

public void Action(Expression<Func<int, int>>);
Action(x => x*x);

In which case what you get is not a function but a parse tree that you can examine at runtime. This is how linq queries build their sql, for example.

edit

To more directly answer the question of when to use one or the other:

You rarely need to declare a new delegate type yourself, although it is occasionally helpful. The framework provides several Func<> types, along with Action<T> and Predicate<T> which are usually all that you need.

When creating a function 'on the fly', there is no advantage to using the anonymous delegate syntax instead of the lambda syntax. Since the lambda syntax is more concise and type-inferred, prefer it.

Abvolt answered 19/7, 2010 at 15:33 Comment(2)
+1 for mentioning expression trees. While you don't need to understand them to use LINQ to SQL, they are an important feature of the language. Also, before lambdas were added in C# 3.0, the only way to get lambda-like semantics was to use anonymous delegates. I recall doing that a lot in C# 2.0 code.Interclavicle
Personally I much prefer anon delegate syntax to lambdas +1Gantlet
U
2

Delegate is just pointer to function. Its just like a "variable", where you can save address to another function that will be called

    public class test {
    Action<int> CallUserCode;

    public test(Action<int> proc){
        CallUserCode = proc;
    }

    void foo(){
        int someValue = 0;
        //do some stuff that needs to call the user procedure
        CallUserCode(someValue);
    }
}

Lambda Expressions is too a delegate, which has simplified syntax and can "create" functions "inline". So the previous example would be called using lambda in following way.

void bar(){
    var t = new test(x => { /* do something with the value i get from foo */});
    t.foo();  //here function foo gets called, which will call 'do something' AND call my lambda expression
}
Utimer answered 19/7, 2010 at 14:58 Comment(0)
M
2

There is one important difference is there where we can use lamda than delegate.

private delegate int emptymethoddel();
// Delegate for method with no params and returns int

The equivalent framework delegate type is: Func<int>

But you cannot create new delegate instance/func from parameterized method.

private int TwoArgMethod(int i, int j)
{
    return i + j;
}

but, with lambda, you can get delegate for the above method.

Func<int> retmethod = () => TwoArgMethod(10, 20);

but for delegate instantiation, we cannot do as below

emptymethoddel retmethod4 = new emptymethoddel(TwoArgMethod(10,20)); 
// mismatch method signature

With lambda, we can get pointers to methods that doesn't match "Func" or any other variants.

Minnich answered 3/4, 2012 at 5:59 Comment(0)
T
1

As the others said, lambdas are a syntax to create delegates inline and anonymously. One thing you can do with lambdas that is not possible with traditional functions are closures. This way you can create functions at runtime with runtime information:

string mystring = SomeObject.GetMyString();
AnotherObject.OnSomeEvent += (eventparams => 
{
  string newstring = string.Format(eventparams.Message, mystring);
  SomeService.PrintEvent(newstring);
}

This way, mystring is incorporated into the delegate and can be used as a variable.

Tannen answered 19/7, 2010 at 15:23 Comment(1)
You can create anonymous delegates, which are closures.Abvolt

© 2022 - 2024 — McMap. All rights reserved.