C# Lambda 表达式:我为什么要使用它们?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/167343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:27:31  来源:igfitidea点击:

C# Lambda expressions: Why should I use them?

c#c#-3.0lambda

提问by Patrick Desjardins

I have quickly read over the Microsoft Lambda Expressiondocumentation.

我已经快速阅读了Microsoft Lambda 表达式文档。

This kind of example has helped me to understand better, though:

不过,这种例子帮助我更好地理解:

delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25

Still, I don't understand why it's such an innovation. It's just a method that dies when the "method variable" ends, right? Why should I use this instead of a real method?

不过,我不明白为什么这是一项创新。它只是一个在“方法变量”结束时死亡的方法,对吗?为什么我应该使用它而不是真正的方法?

采纳答案by Neil Williams

Lambda expressionsare a simpler syntax for anonymous delegates and can be used everywhere an anonymous delegate can be used. However, the opposite is not true; lambda expressions can be converted to expression trees which allows for a lot of the magic like LINQ to SQL.

Lambda 表达式是匿名委托的一种更简单的语法,可以在任何可以使用匿名委托的地方使用。然而,事实并非如此。lambda 表达式可以转换为表达式树,这允许像 LINQ to SQL 这样的很多魔法。

The following is an example of a LINQ to Objectsexpression using anonymous delegates then lambda expressions to show how much easier on the eye they are:

以下是使用匿名委托和 lambda 表达式的LINQ to Objects表达式示例,以显示它们在视觉上有多容易:

// anonymous delegate
var evens = Enumerable
                .Range(1, 100)
                .Where(delegate(int x) { return (x % 2) == 0; })
                .ToList();

// lambda expression
var evens = Enumerable
                .Range(1, 100)
                .Where(x => (x % 2) == 0)
                .ToList();

Lambda expressions and anonymous delegates have an advantage over writing a separate function: they implement closureswhich can allow you to pass local state to the function without adding parametersto the function or creating one-time-use objects.

与编写单独的函数相比,Lambda 表达式和匿名委托有一个优势:它们实现了闭包,可以让您将本地状态传递给函数,而无需向函数添加参数或创建一次性使用的对象。

Expression treesare a very powerful new feature of C# 3.0 that allow an API to look at the structure of an expression instead of just getting a reference to a method that can be executed. An API just has to make a delegate parameter into an Expression<T>parameter and the compiler will generate an expression tree from a lambda instead of an anonymous delegate:

表达式树是 C# 3.0 的一个非常强大的新特性,它允许 API 查看表达式的结构,而不仅仅是获取对可以执行的方法的引用。API 只需将委托参数转换为Expression<T>参数,编译器将从 lambda 生成表达式树,而不是匿名委托:

void Example(Predicate<int> aDelegate);

called like:

称为:

Example(x => x > 5);

becomes:

变成:

void Example(Expression<Predicate<int>> expressionTree);

The latter will get passed a representation of the abstract syntax treethat describes the expression x > 5. LINQ to SQL relies on this behavior to be able to turn C# expressions in to the SQL expressions desired for filtering / ordering / etc. on the server side.

后者将传递描述表达式的抽象语法树的表示x > 5。LINQ to SQL 依靠这种行为能够将 C# 表达式转换为在服务器端过滤/排序/等所需的 SQL 表达式。

回答by Darren Kopp

A lot of the times, you are only using the functionality in one place, so making a method just clutters up the class.

很多时候,您只在一个地方使用该功能,因此创建一个方法只会使类变得混乱。

回答by workmad3

It saves having to have methods that are only used once in a specific place from being defined far away from the place they are used. Good uses are as comparators for generic algorithms such as sorting, where you can then define a custom sort function where you are invoking the sort rather than further away forcing you to look elsewhere to see what you are sorting on.

它避免了在特定位置只使用一次的方法,而不必在远离它们使用的地方定义。很好的用途是作为通用算法(例如排序)的比较器,然后您可以在其中定义自定义排序函数,在其中调用排序,而不是进一步强迫您查看其他地方以查看正在排序的内容。

And it's not really an innovation. LISP has had lambda functions for about 30 years or more.

这并不是真正的创新。LISP 使用 lambda 函数已有大约 30 年或更长时间。

回答by Joseph Daigle

Anonymous functions and expressions are useful for one-off methods that don't benefit from the extra work required to create a full method.

匿名函数和表达式对于不能从创建完整方法所需的额外工作中受益的一次性方法很有用。

Consider this example:

考虑这个例子:

 string person = people.Find(person => person.Contains("Joe"));

versus

相对

 public string FindPerson(string nameContains, List<string> persons)
 {
     foreach (string person in persons)
         if (person.Contains(nameContains))
             return person;
     return null;
 }

These are functionally equivalent.

这些在功能上是等效的。

回答by plinth

It's a way of taking small operation and putting it very close to where it is used (not unlike declaring a variable close to its use point). This is supposed to make your code more readable. By anonymizing the expression, you're also making it a lot harder for someone to break your client code if it the function is used somewhere else and modified to "enhance" it.

这是一种进行小操作并将其放置在非常接近使用位置的方式(与在接近其使用点的位置声明变量不同)。这应该使您的代码更具可读性。通过对表达式进行匿名化,如果该函数在其他地方使用并被修改以“增强”它,那么您也会使某人破坏您的客户端代码变得更加困难。

Similarly, why do you need to use foreach? You can do everything in foreach with a plain for loop or just using IEnumerable directly. Answer: you don't needit but it makes your code more readable.

同样,为什么需要使用foreach?您可以使用普通的 for 循环或直接使用 IEnumerable 在 foreach 中完成所有操作。答:您不需要它,但它使您的代码更具可读性。

回答by Vijesh VP

Lambda expression is a concise way to represent an anonymous method. Both anonymous methods and Lambda expressions allow you define the method implementation inline, however, an anonymous method explicitly requires you to define the parameter types and the return type for a method. Lambda expression uses the type inference feature of C# 3.0 which allows the compiler to infer the type of the variable based on the context. It's is very convenient because that saves us a lot of typing!

Lambda 表达式是表示匿名方法的简洁方式。匿名方法和 Lambda 表达式都允许您内联定义方法实现,但是,匿名方法明确要求您定义方法的参数类型和返回类型。Lambda 表达式使用 C# 3.0 的类型推断功能,该功能允许编译器根据上下文推断变量的类型。这非常方便,因为这为我们节省了大量打字时间!

回答by Scott Dorman

This is just one way of using a lambda expression. You can use a lambda expression anywhereyou can use a delegate. This allows you to do things like this:

这只是使用 lambda 表达式的一种方式。您可以在任何可以使用委托的地方使用 lambda 表达式。这允许您执行以下操作:

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

strings.Find(s => s == "hello");

This code will search the list for an entry that matches the word "hello". The other way to do this is to actually pass a delegate to the Find method, like this:

此代码将在列表中搜索与“hello”一词匹配的条目。另一种方法是实际将委托传递给 Find 方法,如下所示:

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

private static bool FindHello(String s)
{
    return s == "hello";
}

strings.Find(FindHello);

EDIT:

编辑

In C# 2.0, this could be done using the anonymous delegate syntax:

在 C# 2.0 中,这可以使用匿名委托语法来完成:

  strings.Find(delegate(String s) { return s == "hello"; });

Lambda's significantly cleaned up that syntax.

Lambda 显着清理了该语法。

回答by FlySwat

Lambda's cleaned up C# 2.0's anonymous delegate syntax...for example

Lambda 清理了 C# 2.0 的匿名委托语法……例如

Strings.Find(s => s == "hello");

Was done in C# 2.0 like this:

在 C# 2.0 中是这样完成的:

Strings.Find(delegate(String s) { return s == "hello"; });

Functionally, they do the exact same thing, its just a much more concise syntax.

在功能上,它们做完全相同的事情,只是语法更简洁。

回答by Jason Hymanson

Microsoft has given us a cleaner, more convenient way of creating anonymous delegates called Lambda expressions. However, there is not a lot of attention being paid to the expressionsportion of this statement. Microsoft released a entire namespace, System.Linq.Expressions, which contains classes to create expression trees based on lambda expressions. Expression trees are made up of objects that represent logic. For example, x = y + z is an expression that might be part of an expression tree in .Net. Consider the following (simple) example:

Microsoft 为我们提供了一种更简洁、更方便的方式来创建称为 Lambda 表达式的匿名委托。但是,没有太多关注该语句的表达式部分。Microsoft 发布了一个完整的命名空间System.Linq.Expressions,其中包含基于 lambda 表达式创建表达式树的类。表达式树由表示逻辑的对象组成。例如,x = y + z 是一个表达式,它可能是 .Net 中表达式树的一部分。考虑以下(简单)示例:

using System;
using System.Linq;
using System.Linq.Expressions;


namespace ExpressionTreeThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<int, int>> expr = (x) => x + 1; //this is not a delegate, but an object
            var del = expr.Compile(); //compiles the object to a CLR delegate, at runtime
            Console.WriteLine(del(5)); //we are just invoking a delegate at this point
            Console.ReadKey();
        }
    }
}

This example is trivial. And I am sure you are thinking, "This is useless as I could have directly created the delegate instead of creating an expression and compiling it at runtime". And you would be right. But this provides the foundation for expression trees. There are a number of expressions available in the Expressions namespaces, and you can build your own. I think you can see that this might be useful when you don't know exactly what the algorithm should be at design or compile time. I saw an example somewhere for using this to write a scientific calculator. You could also use it for Bayesiansystems, or for genetic programming(AI). A few times in my career I have had to write Excel-like functionality that allowed users to enter simple expressions (addition, subtrations, etc) to operate on available data. In pre-.Net 3.5 I have had to resort to some scripting language external to C#, or had to use the code-emitting functionality in reflection to create .Net code on the fly. Now I would use expression trees.

这个例子很简单。我相信你在想,“这没用,因为我可以直接创建委托,而不是创建一个表达式并在运行时编译它”。你会是对的。但这为表达式树提供了基础。Expressions 命名空间中有许多可用的表达式,您可以构建自己的表达式。我认为您可以看到,当您在设计或编译时不确切知道算法应该是什么时,这可能很有用。我在某处看到了一个使用它来编写科学计算器的示例。您也可以将其用于贝叶斯系统或遗传编程(人工智能)。在我的职业生涯中,有几次我不得不编写类似 Excel 的功能,允许用户输入简单的表达式(加法、减法等)来对可用数据进行操作。在 .Net 3.5 之前的版本中,我不得不求助于 C# 外部的一些脚本语言,或者不得不在反射中使用代码发出功能来动态创建 .Net 代码。现在我会使用表达式树。

回答by agnieszka

I found them useful in a situation when I wanted to declare a handler for some control's event, using another control. To do it normally you would have to store controls' references in fields of the class so that you could use them in a different method than they were created.

当我想使用另一个控件为某个控件的事件声明一个处理程序时,我发现它们很有用。要正常执行此操作,您必须将控件的引用存储在类的字段中,以便您可以在与创建它们不同的方法中使用它们。

private ComboBox combo;
private Label label;

public CreateControls()
{
    combo = new ComboBox();
    label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += new EventHandler(combo_SelectedIndexChanged);
}

void combo_SelectedIndexChanged(object sender, EventArgs e)
{
    label.Text = combo.SelectedValue;
}

thanks to lambda expressions you can use it like this:

多亏了 lambda 表达式,您可以像这样使用它:

public CreateControls()
{
    ComboBox combo = new ComboBox();
    Label label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += (s, e) => {label.Text = combo.SelectedValue;};
}

Much easier.

容易多了。