lambda表达式与方法组之间的区别

Ale*_*dre 16 c# lambda method-group

有什么区别

Class1.Method1<Guid, BECustomer>("cId", Facade.Customers.GetSingle);
Run Code Online (Sandbox Code Playgroud)

Class1.Method1<Guid, BECustomer>("cId", x => Facade.Customers.GetSingle(x));
Run Code Online (Sandbox Code Playgroud)

Resharper建议使用第一个表达式.

Dan*_*rth 20

结果没有区别.但是,第二个创建了一个额外的重定向:代码将首先调用您的匿名方法,获取一个名为的参数x,然后Facade.Customers.GetSingle使用该参数调用.这种重定向根本没有任何好处,这就是ReSharper告诉您使用第一种替代方案的原因.

  • 封闭方面有所不同.假设`Facade.Customers`随着时间的推移而变化.然后第一个(来自命名方法的方法组)将保留原始的`Customers`,而第二个(来自lambda的匿名函数)将反映新的`Customers`(`Customers`由匿名函数重新评估).所以在第二个方面,评估是"推迟"的.如果这很难理解,请尝试以下代码:`string test ="12345"; Func <string,bool> f = test.Contains; Func <string,bool> g = x => test.Contains(x); test ="改变了!"; bool a = f("34"); bool b = g("34");`. (12认同)
  • 它不限于单参数lambda - 方法组适用于任何匹配的委托签名. (3认同)
  • @Vladislav:你是什么意思?第一个版本不是第二个版本的语法糖.第一个传递`GetSingle`方法的"函数指针",而第二个传递匿名方法的"函数指针". (2认同)

dah*_*byk 13

在幕后,如果使用lambda表达式,编译器会生成更多代码.使用方法组,它只是创建一个指向该方法的新委托:

L_0001: ldstr "cId"
L_0006: ldnull 
L_0007: ldftn void Facade/Customers::GetSingle(valuetype [mscorlib]System.Guid)
L_000d: newobj instance void [mscorlib]System.Action`1<valuetype [mscorlib]System.Guid>::.ctor(object, native int)
L_0012: call void Class1::Method1<valuetype [mscorlib]System.Guid, class BECustomer>(string, class [mscorlib]System.Action`1<!!0>)
Run Code Online (Sandbox Code Playgroud)

使用lambda表达式,在类<Test>b__0上创建一个匿名方法(在L_0025上),代理引用它:

L_0018: ldstr "cId"
L_001d: ldsfld class [mscorlib]System.Action`1<valuetype [mscorlib]System.Guid> Class1::CS$<>9__CachedAnonymousMethodDelegate1
L_0022: brtrue.s L_0037
L_0024: ldnull 
L_0025: ldftn void Class1::<Test>b__0(valuetype [mscorlib]System.Guid)
L_002b: newobj instance void [mscorlib]System.Action`1<valuetype [mscorlib]System.Guid>::.ctor(object, native int)
L_0030: stsfld class [mscorlib]System.Action`1<valuetype [mscorlib]System.Guid> Class1::CS$<>9__CachedAnonymousMethodDelegate1
L_0035: br.s L_0037
L_0037: ldsfld class [mscorlib]System.Action`1<valuetype [mscorlib]System.Guid> Class1::CS$<>9__CachedAnonymousMethodDelegate1
L_003c: call void Class1::Method1<valuetype [mscorlib]System.Guid, class BECustomer>(string, class [mscorlib]System.Action`1<!!0>)
Run Code Online (Sandbox Code Playgroud)

  • lambda 表达式生成更多代码,但根据 [这篇文章](http://vibrantcode.com/2013/02/19/lambdas-vs-method-groups/),lambda 表达式实际上比方法组快一点并且使用更少的内存,因为“方法组版本每次运行时都会分配一个新对象,而 lambda 版本使用实例(或静态,根据需要)字段来缓存委托。” (3认同)