Understanding Lambda expressions and delegates [closed]

自闭症网瘾萝莉.ら 提交于 2020-01-30 14:36:19

问题


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.


回答1:


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 ;-)




回答2:


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.



回答3:


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.




回答4:


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
}



回答5:


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.




回答6:


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.



来源:https://stackoverflow.com/questions/3282103/understanding-lambda-expressions-and-delegates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!