编译后,两者之间是否有区别:
delegate { x = 0; }
和
() => { x = 0 }
?
简短的回答:没有。
可能不相关的更长答案:
Func
或Action
),您将获得匿名委托。编辑:这是表达式的一些链接。
我喜欢艾米的回答,但我认为我会很迂腐。问题是“一旦编译” - 这表明两个表达式都已编译。它们怎么能同时编译,但一个被转换为委托,一个被转换为表达式树?这是一个棘手的问题——你必须使用匿名方法的另一个特性;唯一不被 lambda 表达式共享的。如果您指定匿名方法而不指定参数列表,则它与任何返回 void 且不带任何out
参数的委托类型兼容。有了这些知识,我们应该能够构造两个重载以使表达式完全明确但非常不同。
但是灾难来袭!至少在 C# 3.0 中,您不能将带有块体的 lambda 表达式转换为表达式 - 也不能将带有赋值的 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; } );
}
}
哎哟。记住孩子们,每次你重载从基类继承的方法时,小猫就会开始哭泣。
在上面的两个示例中,没有区别,为零。
表达方式:
() => { x = 0 }
是带有语句体的 Lambda 表达式,因此不能编译为表达式树。事实上它甚至没有编译,因为它需要在 0 后加一个分号:
() => { x = 0; } // Lambda statement body
() => x = 0 // Lambda expression body, could be an expression tree.
艾米 B 是正确的。请注意,使用表达式树可能有一些好处。LINQ to SQL 将检查表达式树并将其转换为 SQL。
您还可以使用 lamdas 和表达式树来有效地将类成员的名称以重构安全的方式传递给框架。 起订量就是一个例子。
它们是有区别的
例子:
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(delegate
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
我用 lambda:(error) 替换
var mytask = Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
return 2712;
});
mytask.ContinueWith(()=>
{
_backgroundTask.ContinueTask(() =>lblPercent.Content = mytask.Result.ToString(CultureInfo.InvariantCulture));
});
这里有一些基础知识。
这是一个匿名方法
(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);