我已经快速阅读了 Microsoft Lambda Expression 文档。

这种例子让我更好地理解:

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

但是,我不明白为什么这是一项创新。它只是一个方法,当<!> quot;方法变量<!>结束,对吗?我为什么要使用它而不是真正的方法?

有帮助吗?

解决方案

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

以下是使用 LINQ to Objects 表达式的示例匿名委托然后lambda表达式显示他们的眼睛有多容易:

// 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表达式和匿名委托比编写单独的函数更有优势:它们实现了闭包允许您将本地状态传递给函数而不添加参数功能或创建一次性使用对象。

表达树是一个非常强大的新功能C#3.0允许API查看表达式的结构,而不是只获取对可执行方法的引用。 API只需将委托参数设置为 Expression&lt; T&gt; 参数,编译器将从lambda而不是匿名委托生成表达式树:

void Example(Predicate<int> aDelegate);

调用如:

Example(x => x > 5);

变为:

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

后者将通过抽象语法树的表示来描述表达式 x&gt; 5 。 LINQ to SQL依赖于这种行为,能够将C#表达式转换为服务器端过滤/排序等所需的SQL表达式。

其他提示

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

考虑这个例子:

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

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

这些在功能上是等效的。

我发现它们在我想要使用另一个控件为某个控件的事件声明处理程序的情况下很有用。 通常,您必须将控件的引用存储在类的字段中,以便您可以使用与创建它们不同的方法来使用它们。

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

感谢lambda表达式,你可以像这样使用它:

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

更容易。

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

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

在C#2.0中完成了这样的事情:

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

从功能上讲,它们完全相同,只是一种更简洁的语法。

这只是使用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");

此代码将在列表中搜索与单词“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);

修改

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

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

Lambda显着清理了这种语法。

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

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

它可以节省必须在特定位置使用一次的方法远离它们使用的位置。良好的用途是作为通用算法(如排序)的比较器,然后您可以在其中定义自定义排序函数,您可以在其中调用排序而不是进一步强制您查看其他位置以查看您要排序的内容。

这并不是一项创新。 LISP具有λ功能约30年或更长时间。

lambda表达式类似于代替委托实例编写的匿名方法。

delegate int MyDelagate (int i);
MyDelagate delSquareFunction = x => x * x;

考虑lambda表达式 x =&gt; x * x;

  

输入参数值为x(在=&gt;的左侧)

     

函数逻辑是x * x(在=&gt;的右侧)

lambda表达式的代码可以是语句块而不是表达式。

x => {return x * x;};

示例

注意: Func 是预定义的通用委托。

    Console.WriteLine(MyMethod(x => "Hi " + x));

    public static string MyMethod(Func<string, string> strategy)
    {
        return strategy("Lijo").ToString();
    }

<强>参考

  1. 如何委托&amp;界面可以互换使用?

您还可以在编写通用代码时使用lambda表达式来处理您的方法。

例如:用于计算方法调用所用时间的通用函数。 (即 Action 在这里)

public static long Measure(Action action)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    action();
    sw.Stop();
    return sw.ElapsedMilliseconds;
}

你可以使用lambda表达式调用上面的方法,如下所示,

var timeTaken = Measure(() => yourMethod(param));

Expression允许您从方法中获取返回值,也可以从param中获取

var timeTaken = Measure(() => returnValue = yourMethod(param, out outParam));

很多时候,你只是在一个地方使用这个功能,所以制作一个方法只会让课堂变得混乱。

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

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

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

创新的类型是安全性和透明度。虽然您没有声明lambda表达式的类型,但它们是推断的,可以由代码搜索,静态分析,重构工具和运行时反射使用。

例如,在您可能使用SQL并且可能获得SQL注入攻击之前,因为黑客传递了一个通常需要数字的字符串。现在你将使用一个LINQ lambda表达式,它受到保护。

在纯委托上构建LINQ API是不可能的,因为它需要在评估它们之前将表达式树组合在一起。

2016年,大多数流行语言都支持 lambda expression ,而C#是其中之一主流命令式语言中这种演变的先驱。

这可能是为什么要使用lambda表达式的最佳解释 - &gt; https://youtu.be/j9nj5dTo54Q

总之,它是为了提高代码可读性,通过重用而不是复制代码来减少错误的机会,并利用幕后发生的优化。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top