简体   繁体   English

lambda 表达式的意义何在?

[英]What's the point of a lambda expression?

After reading this article , I can't figure out why lambda expressions are ever used.读完这篇文章后,我不明白为什么曾经使用过 lambda 表达式。 To be fair, I don't think I have a proper understanding of what delegates and expression tree types are, but I don't understand why anyone would use a lambda expression instead of a declared function.公平地说,我不认为我对什么是委托和表达式树类型有正确的理解,但我不明白为什么有人会使用 lambda 表达式而不是声明的 function。 Can someone enlighten me?有人可以启发我吗?

First: brevity and locality :第一:简洁性和局部性

Which would you rather write, read and maintain?您更愿意编写、阅读和维护哪个? This:这个:

    var addresses = customers.Select(customer=>customer.Address);

or:或者:

static private Address GetAddress(Customer customer)
{
     return customer.Address;
}

... a thousand lines later ...

    var addresses = customers.Select(GetAddress);

What's the point of cluttering up your program with hundreds or thousands of four-line functions when you could just put the code you need where you need it as a short expression?当你可以把你需要的代码作为一个简短的表达式放在你需要的地方时,用成百上千个四行函数把你的程序弄得乱七八糟有什么意义呢?

Second: lambdas close over local scopes第二: lambda 关闭本地范围

Which would you rather read, write and maintain, this:您更愿意阅读、编写和维护哪个:

var currentCity = GetCurrentCity();
var addresses = customers.Where(c=>c.City == currentCity).Select(c=>c.Address);

or:或者:

static private Address GetAddress(Customer customer)
{
     return customer.Address;
}

private class CityGetter
{
    public string currentCity;
    public bool DoesCityMatch(Customer customer)
    {
        return customer.City == this.currentCity;
    }
}

....

var currentCityGetter = new CityGetter();
currentCityGetter.currentCity = GetCurrentCity();
var addresses = customers.Where(currentCityGetter.DoesCityMatch).Select(GetAddress);

All that vexing code is written for you when you use a lambda.当您使用 lambda 时,所有这些令人烦恼的代码都是为您编写的。

Third: Query comprehensions are rewritten to lambdas for you第三:为您将查询理解重写为 lambdas

When you write:当你写:

var addresses = from customer in customers
                where customer.City == currentCity 
                select customer.Address;

it is transformed into the lambda syntax for you.它为您转换为 lambda 语法。 Many people find this syntax pleasant to read, but we need the lambda syntax in order to actually make it work.很多人觉得这个语法读起来很舒服,但是我们需要 lambda 语法才能真正让它工作。

Fourth: lambdas are optionally type-inferred第四: lambdas 是可选的类型推断

Notice that we don't have to give the type of "customer" in the query comprehension above, or in the lambda versions, but we do have to give the type of the formal parameter when declaring it as a static method.请注意,我们不必在上面的查询理解中或 lambda 版本中给出“客户”的类型,但在将其声明为 static 方法时,我们必须给出形式参数的类型。 The compiler is smart about inferring the type of a lambda parameter from context.编译器很聪明地从上下文中推断出 lambda 参数的类型。 This makes your code less redundant and more clear.这使您的代码更少冗余,更清晰。

Fifth: Lambdas can become expression trees第五: Lambda可以变成表达式树

Suppose you want to ask a web server "send me the addresses of the customers that live in the current city."假设您想询问 web 服务器“将居住在当前城市的客户的地址发送给我”。 Do you want to (1) pull down a million customers from the web site and do the filtering on your client machine, or (2) send the web site an object that tells it "the query contains a filter on the current city and then a selection of the address"?您是否要 (1) 从 web 站点拉下一百万客户并在您的客户端计算机上进行过滤,或者 (2) 向 web 站点发送 object 站点一个 object 的当前城市过滤器然后告诉它“选择地址”? Let the server do the work and send you only the result that match.让服务器完成工作并只向您发送匹配的结果。

Expression trees allow the compiler to turn the lambda into code that can be transformed into another query format at runtime and sent to a server for processing.表达式树允许编译器将 lambda 转换为可以在运行时转换为另一种查询格式并发送到服务器进行处理的代码。 Little helper methods that run on the client do not.在客户端上运行的小助手方法不会。

The primary reason you'd use a lambda over a declared function is when you need to use a piece of local information in the delegate expression.在声明的 function 上使用 lambda 的主要原因是当您需要在委托表达式中使用一条本地信息时。 For example例如

void Method(IEnumerable<Student> students, int age) {
  var filtered = students.Where(s => s.Age == age);
  ...
}

Lambdas allow for the easy capture of local state to be used within the delegate expression. Lambda 允许轻松捕获要在委托表达式中使用的本地 state。 To do this manually requires a lot of work because you need to declare both a function and a containing type to hold the state.手动执行此操作需要大量工作,因为您需要声明 function 和包含类型以保存 state。 For example here's the above without a lambda例如,上面没有 lambda

void Method(IEnumerable<Student> students, int age) {
  var c = new Closure() { Age = age };
  var filtered = students.Where(c.WhereDelegate);
  ...
}

class Closure {
  public int age;
  bool WhereDelegate(Student s) {
    return s.Age == age;
  }
}

Typing this out is tedious and error prone.输入这个很乏味并且容易出错。 Lambda expressions automate this process. Lambda 表达式自动执行此过程。

Let's leave expression trees out of the equation for the moment and pretend that lambdas are just a shorter way to write delegates.让我们暂时将表达式树排除在等式之外,并假设 lambdas 只是编写委托的一种更短的方法。

This is still a big win in the realm of statically typed languages like C# because such languages require lots of code to be written in order to achieve relatively simple goals.在 C# 等静态类型语言的 realm 中,这仍然是一个巨大的胜利,因为此类语言需要编写大量代码才能实现相对简单的目标。 Do you need to compare sort an array of strings by string length?您是否需要按字符串长度比较对字符串数组进行排序? You need to write a method for that.你需要为此编写一个方法。 And you need to write a class to put the method into.而且你需要写一个 class 把方法放进去。 And then good practice dictates that this class should be in its own source file.然后良好的做法规定这个 class 应该在它自己的源文件中。 In any but the smallest project, all of this adds up.在除了最小的项目之外的任何项目中,所有这些都会加起来。 When we 're talking about small stuff, most people want a less verbose path to the goal and lambdas are about as terse as it can get.当我们谈论小事情时,大多数人都希望实现目标的路径不那么冗长,而 lambda 则尽可能简洁。

Furthermore, lambdas can easily create closures (capture variables from the current scope and extend their lifetime).此外,lambda 可以轻松创建闭包(从当前的 scope 中捕获变量并延长它们的生命周期)。 This isn't magic (the compiler does it by creating a hidden class and performing some other transformations that you can do yourself), but it's so much more convenient than the manual alternative.这并不神奇(编译器通过创建隐藏的 class 并执行您可以自己进行的一些其他转换来实现),但它比手动替代方法方便得多。

And then there are expression trees: a way for you to write code and have the compiler transform this code into a data structure that can be parsed, modified and even compiled at runtime.然后是表达式树:一种编写代码并让编译器将此代码转换为可以在运行时解析、修改甚至编译的数据结构的方法。 This is an extremely powerful feature that opens the door to impressive functionality (which I definitely consider LINQ to be).这是一个非常强大的功能,它为令人印象深刻的功能打开了大门(我绝对认为 LINQ 就是这样)。 And you get it "for free".你可以“免费”获得它。

http://msdn.microsoft.com/en-us/magazine/cc163362.aspx http://msdn.microsoft.com/en-us/magazine/cc163362.aspx

Great article on what lambdas are, and why you can/should use them.关于什么是 lambdas 以及为什么可以/应该使用它们的好文章。

Essentially, the lambda expression provides a shorthand for the compiler to emit methods and assign them to delegates;本质上,lambda 表达式为编译器提供了一种简写方式来发出方法并将它们分配给委托; this is all done for you.这一切都是为你完成的。 The benefit you get with a lambda expression that you don't get from a delegate/function combination is that the compiler performs automatic type inference on the lambda arguments使用 lambda 表达式获得的好处是,编译器对 lambda arguments 执行自动类型推断

They are heavily used with LINQ, actually LINQ would be pretty bad without it.它们大量与 LINQ 一起使用,实际上 LINQ 没有它会很糟糕。 You can do stuff like:您可以执行以下操作:

Database.Table.Where(t => t.Field == "Hello"); Database.Table.Where(t => t.Field == "你好");

Lambda makes code short and sweet. Lambda 使代码简短而甜美。 Consider the following two examples:考虑以下两个示例:

public class Student公共 class 学生

{


   public string Name { get; set; }
   public float grade { get; set; }
   public static void failed(List<Student> studentList, isFaild fail)
   {
       foreach (Student student in studentList)
       {
          if(fail(student))
          {
    Console.WriteLine("Sorry" + " "+student.Name + " "+  "you faild this exam!");
          }
       }
   }

public delegate bool isFaild(Student myStudent);公共代表 bool isFaild(Student myStudent);

class Program
{
    static void Main(string[] args)
    {
        List<Student> studentsList  = new List<Student>();
        studentsList .Add(new Student { ID = 101, Name = "Rita", grade = 99 });
        studentsList .Add(new Student { ID = 102, Name = "Mark", grade = 48 });
        Student.failed(studentsList, std => std.grade < 60);  // with Lamda

          }
       }

private static bool isFaildMethod(Student myStudent) // without Lambda私人 static bool isFaildMethod(Student myStudent) // 没有 Lambda

{ {

if (myStudent.grade < 60)如果 (myStudent.grade < 60)

        {

            return true;

        }
        else
        {
            return false;
        }
    }

They make it easy to pass a simple piece of functionality to another function.它们可以轻松地将一个简单的功能传递给另一个 function。 For example, I may want to perform an arbitrary, small function on every item in a list (perhaps I want to square it, or take the square root, or so on).例如,我可能想对列表中的每个项目执行任意的小 function(也许我想对其平方,或取平方根,等等)。 Rather than writing a new loop and function for each of these situations, I can write it once, and apply my arbitrary functionality defined later to each item.与其为每种情况编写一个新循环和 function,不如只编写一次,然后将我稍后定义的任意功能应用于每个项目。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM