了解 Lambda 表达式和委托

发布于 2024-09-10 04:29:35 字数 1437 浏览 7 评论 0原文

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

缘字诀 2024-09-17 04:29:35

委托是一种可以用作变量的方法,例如字符串等。例如,您可以使用一个参数声明委托方法:

delegate void OneArgumentDelegate(string argument);

它不执行任何操作,很像接口。如果任何类中有一个带有如下参数的方法:

void SomeMethod(string someArgument) {}

匹配委托的签名,因此可以分配给其类型的变量:

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

然后可以将它们作为参数传递给方法并调用,如下所示:

void Main()
{
  DoStuff(PrintString);
}

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

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

这将输出 Hello!

Lambda 表达式是 DoStuff(PrintString) 的简写,因此您不必为要使用的每个委托变量创建方法。您“创建”一个传递给该方法的临时方法。它的工作原理是这样的:

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

Lambda 表达式只是一种简写,您不妨创建一个单独的方法并将其传递下去。我希望你现在能更好地理解它;-)

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

救星 2024-09-17 04:29:35

Delegate 是一个保存函数引用的对象。几个不同的委托可能指向同一个函数。委托的类型定义了它可能指向的函数的足迹。

Lambda 表达式 是一个没有名称的函数。执行此函数的唯一方法是让一个委托指向该函数。 Lambda 表达式通常定义在需要委托给具有给定足迹的函数的地方。这对于使代码不那么冗长,同时更具描述性和灵活性很有用,

我建议您在有一些将从不同位置调用的代码时使用命名函数和它的委托。一个常见的示例是您想要附加到多个事件生成器的事件侦听器。

考虑编写单独函数的另一点是代码的复杂性。如果您在 lambda 表达式中编写整个程序,这对任何人都没有帮助。

另一方面,您经常需要一些琐碎的处理,希望以回调的方式执行。这就是您可能喜欢 lambda 表达式的地方。

lambda 表达式的优点是它们继承了定义它们的作用域,这样您就可以轻松地在 lambda 表达式中添加变量,从而在其中传递大量信息。不过你应该小心,请参阅备注部分
这篇文章。

Labda 与 LINQ 结合使用非常出色。

最后,我必须引用另一个必读的msdn部分:

当您使用基于方法的语法调用 Enumerable 类中的Where 方法(如在 LINQ to Objects 和 LINQ to XML 中所做的那样)时,参数是委托类型 System.Func。 lambda 表达式是创建该委托的最便捷方法。例如,当您在 System.Linq.Queryable 类中调用相同的方法时(如在 LINQ to SQL 中所做的那样),则参数类型为 System.Linq.Expressions.Expression,其中 Func 是最多具有 16 个的任何 Func 委托输入参数。同样,lambda 表达式只是构建表达式树的一种非常简洁的方法。 lambda 允许Where 调用看起来相似,尽管实际上从lambda 创建的对象类型不同。

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.

想你的星星会说话 2024-09-17 04:29:35

没有人提到匿名代表。您可以即时创建委托,而无需声明它们:

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

这只是 lambda 语法的更详细版本:

Action(x => x*x);

另请注意,lambda 语法具有更积极的类型推断。另一个区别是 lambda 表示法可用于声明表达式树:

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

在这种情况下,您得到的不是函数,而是可以在运行时检查的解析树。例如,这就是 linq 查询构建其 sql 的方式。

编辑

要更直接地回答何时使用其中之一的问题:

您很少需要自己声明新的委托类型,尽管它偶尔会有所帮助。该框架提供了多种 Func<> 类型,以及 ActionPredicate,这些通常都是您所需要的。

当“即时”创建函数时,使用匿名委托语法而不是 lambda 语法没有任何优势。由于 lambda 语法更加简洁并且可以进行类型推断,因此更喜欢它。

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.

小ぇ时光︴ 2024-09-17 04:29:35

委托只是指向函数的指针。它就像一个“变量”,您可以将地址保存到另一个称为

    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 表达式的函数,它也是一个委托,它具有简化的语法,并且可以“内联”“创建”函数。
因此,前面的示例将按以下方式使用 lambda 进行调用。

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
}

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
}
泪冰清 2024-09-17 04:29:35

有一个重要的区别是我们可以使用 lamda 而不是 delegate。

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

等效的框架委托类型是: Func

但是您无法从参数化方法创建新的委托实例/func。

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

但是,使用 lambda ,您可以获取上述方法的委托。

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

但对于委托实例化,我们不能像下面那样

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

使用 lambda,我们可以获得指向与“Func”或任何其他变体不匹配的方法的指针。

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.

心是晴朗的。 2024-09-17 04:29:35

正如其他人所说,lambda 是一种内联和匿名创建委托的语法。使用 lambda 可以做的一件事是传统函数做不到的,那就是闭包。这样,您就可以在运行时使用运行时信息创建函数:

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

这样,mystring 就会合并到委托中并可以用作变量。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文