繁体   English   中英

lambda 表达式的意义何在?

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

读完这篇文章后,我不明白为什么曾经使用过 lambda 表达式。 公平地说,我不认为我对什么是委托和表达式树类型有正确的理解,但我不明白为什么有人会使用 lambda 表达式而不是声明的 function。 有人可以启发我吗?

第一:简洁性和局部性

您更愿意编写、阅读和维护哪个? 这个:

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

或者:

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

... a thousand lines later ...

    var addresses = customers.Select(GetAddress);

当你可以把你需要的代码作为一个简短的表达式放在你需要的地方时,用成百上千个四行函数把你的程序弄得乱七八糟有什么意义呢?

第二: lambda 关闭本地范围

您更愿意阅读、编写和维护哪个:

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

或者:

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

当您使用 lambda 时,所有这些令人烦恼的代码都是为您编写的。

第三:为您将查询理解重写为 lambdas

当你写:

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

它为您转换为 lambda 语法。 很多人觉得这个语法读起来很舒服,但是我们需要 lambda 语法才能真正让它工作。

第四: lambdas 是可选的类型推断

请注意,我们不必在上面的查询理解中或 lambda 版本中给出“客户”的类型,但在将其声明为 static 方法时,我们必须给出形式参数的类型。 编译器很聪明地从上下文中推断出 lambda 参数的类型。 这使您的代码更少冗余,更清晰。

第五: Lambda可以变成表达式树

假设您想询问 web 服务器“将居住在当前城市的客户的地址发送给我”。 您是否要 (1) 从 web 站点拉下一百万客户并在您的客户端计算机上进行过滤,或者 (2) 向 web 站点发送 object 站点一个 object 的当前城市过滤器然后告诉它“选择地址”? 让服务器完成工作并只向您发送匹配的结果。

表达式树允许编译器将 lambda 转换为可以在运行时转换为另一种查询格式并发送到服务器进行处理的代码。 在客户端上运行的小助手方法不会。

在声明的 function 上使用 lambda 的主要原因是当您需要在委托表达式中使用一条本地信息时。 例如

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

Lambda 允许轻松捕获要在委托表达式中使用的本地 state。 手动执行此操作需要大量工作,因为您需要声明 function 和包含类型以保存 state。 例如,上面没有 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;
  }
}

输入这个很乏味并且容易出错。 Lambda 表达式自动执行此过程。

让我们暂时将表达式树排除在等式之外,并假设 lambdas 只是编写委托的一种更短的方法。

在 C# 等静态类型语言的 realm 中,这仍然是一个巨大的胜利,因为此类语言需要编写大量代码才能实现相对简单的目标。 您是否需要按字符串长度比较对字符串数组进行排序? 你需要为此编写一个方法。 而且你需要写一个 class 把方法放进去。 然后良好的做法规定这个 class 应该在它自己的源文件中。 在除了最小的项目之外的任何项目中,所有这些都会加起来。 当我们谈论小事情时,大多数人都希望实现目标的路径不那么冗长,而 lambda 则尽可能简洁。

此外,lambda 可以轻松创建闭包(从当前的 scope 中捕获变量并延长它们的生命周期)。 这并不神奇(编译器通过创建隐藏的 class 并执行您可以自己进行的一些其他转换来实现),但它比手动替代方法方便得多。

然后是表达式树:一种编写代码并让编译器将此代码转换为可以在运行时解析、修改甚至编译的数据结构的方法。 这是一个非常强大的功能,它为令人印象深刻的功能打开了大门(我绝对认为 LINQ 就是这样)。 你可以“免费”获得它。

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

关于什么是 lambdas 以及为什么可以/应该使用它们的好文章。

本质上,lambda 表达式为编译器提供了一种简写方式来发出方法并将它们分配给委托; 这一切都是为你完成的。 使用 lambda 表达式获得的好处是,编译器对 lambda arguments 执行自动类型推断

它们大量与 LINQ 一起使用,实际上 LINQ 没有它会很糟糕。 您可以执行以下操作:

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

Lambda 使代码简短而甜美。 考虑以下两个示例:

公共 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!");
          }
       }
   }

公共代表 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

          }
       }

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

{

如果 (myStudent.grade < 60)

        {

            return true;

        }
        else
        {
            return false;
        }
    }

它们可以轻松地将一个简单的功能传递给另一个 function。 例如,我可能想对列表中的每个项目执行任意的小 function(也许我想对其平方,或取平方根,等等)。 与其为每种情况编写一个新循环和 function,不如只编写一次,然后将我稍后定义的任意功能应用于每个项目。

暂无
暂无

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

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