委托关键字与拉姆达符号委托关键字与拉姆达符号(delegate keyword vs. lambda

2019-05-10 12:21发布

一旦被编译,有没有之间的差异:

delegate { x = 0; }

() => { x = 0 }

Answer 1:

简短的回答:没有。

较长的答案可能是不相关的:

  • 如果您分配lambda来委托类型(如FuncAction ),你会得到一个匿名委托。
  • 如果您分配lambda来表达式类型,你会得到一个表达式树,而不是匿名委托。 然后,表达式树可以被编译为一个匿名委托。

编辑:下面是一些表达式链接。

  • System.Linq.Expression.Expression(TDelegate) (从这里开始)。
  • LINQ内存与代表(如System.Func)使用System.Linq.Enumerable 。 LINQ到SQL(和其他东西)与表达式使用System.Linq.Queryable 。 看看这些方法的参数。
  • 一个来自ScottGu解释 。 简而言之,LINQ的内存会产生一些匿名的方法来解决您的查询。 LINQ到SQL会产生一个代表查询表达式目录树,然后翻译该树为T-SQL。 LINQ到实体会产生一个代表查询表达式目录树,然后翻译该树为平台相应的SQL。


Answer 2:

我喜欢大卫的答案,但我以为我会很迂腐。 这个问题说,“一旦它编译” -这表明两个表达式被编译。 他们俩怎么能编译,但有一个被转换成一个委托和一个表达式目录树? 这是一个棘手的一个 - 你必须使用的匿名方法的另一特点; 其不受lambda表达式共享唯一的一个。 如果没有指定参数列表指定一个匿名方法它与任何委托类型返回void,没有任何兼容out参数。 有了这些知识,我们应该能够构建两个重载,使表达式完全明确,但有很大不同。

但是,灾难降临! 至少用C#3.0,则无法转换与块体的λ表达到表达 - 也无法将转换lambda表达式与在所述本体中的分配(即使它被用作返回值)。 这可以用C#4.0和.NET 4.0,这允许更多的在一个表达式树中表达发生改变。 所以换句话说,MojoFilter碰巧给的例子,这两个几乎总是被转换为同样的事情。 (在一分钟内的更多细节。)

我们可以使用委托参数伎俩,如果我们改变身体一点点,但:

using System;
using System.Linq.Expressions;

public class Test
{
    static void Main()
    {
        int x = 0;
        Foo( () => x );
        Foo( delegate { return x; } );
    }

    static void Foo(Func<int, int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }

    static void Foo(Expression<Func<int>> func)
    {
        Console.WriteLine("I suspect the lambda expression...");
    }
}

可是等等! 我们甚至可以不使用表达式树区分这两种,如果我们够狡猾。 下面的示例使用重载决策规则(和匿名委托匹配把戏)...

using System;
using System.Linq.Expressions;

public class Base
{
    public void Foo(Action action)
    {
        Console.WriteLine("I suspect the lambda expression...");
    }
}

public class Derived : Base
{
    public void Foo(Action<int> action)
    {
        Console.WriteLine("I suspect the anonymous method...");
    }
}

class Test
{
    static void Main()
    {
        Derived d = new Derived();
        int x = 0;
        d.Foo( () => { x = 0; } );
        d.Foo( delegate { x = 0; } );
    }
}

哎哟。 记住孩子们,每次你重载从基类继承的方法的时候,一只小猫开始哭闹。



Answer 3:

大卫·B是正确的。 请注意,可以使用表达式树的优势。 的LINQ to SQL将检查表达式树并将其转换为SQL。

您也可以玩lamdas和表达式树的技巧类成员的姓名,有效地传递给在重构安全方式的框架。 Moq的是这样的一个例子。



Answer 4:

在以上两个例子有没有区别,零。

表达方式:

() => { x = 0 }

是一个Lambda表达式with语句身体,所以它不能被编译成一个表达式树。 事实上,它甚至不编译,因为它0后需要一个分号:

() => { x = 0; } // Lambda statement body
() => x = 0      // Lambda expression body, could be an expression tree. 


Answer 5:

它们是有区别的

例:

var mytask = Task.Factory.StartNew(() =>
{
    Thread.Sleep(5000);
    return 2712;
});
mytask.ContinueWith(delegate
{
    _backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});   

和我一起的λ替换:(错误)

var mytask = Task.Factory.StartNew(() =>
{
    Thread.Sleep(5000);
    return 2712;
});
mytask.ContinueWith(()=>
{
    _backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});


Answer 6:

这里的一些基础知识。

这是一个匿名方法

(string testString) => { Console.WriteLine(testString); };

由于匿名方法没有名字,我们需要在其中我们可以指定这两种方法或表达式的委托。 例如

delegate void PrintTestString(string testString); // declare a delegate

PrintTestString print = (string testString) => { Console.WriteLine(testString); }; 
print();

同样的,lambda表达式。 通常我们需要一个委托使用它们

s => s.Age > someValue && s.Age < someValue    // will return true/false

我们可以用一个FUNC代表用这句话。

Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ;

bool result = checkStudentAge ( Student Object);


文章来源: delegate keyword vs. lambda notation