Разница между лямбда-выражением и группой методов - PullRequest
15 голосов
/ 12 июля 2011

В чем разница между

Class1.Method1<Guid, BECustomer>("cId", Facade.Customers.GetSingle);

и

Class1.Method1<Guid, BECustomer>("cId", x => Facade.Customers.GetSingle(x));

?

Решарпер предлагает использовать первое выражение.

Ответы [ 3 ]

19 голосов
/ 12 июля 2011

Нет никакой разницы в отношении результата.Однако второй создает дополнительное перенаправление: код сначала вызовет ваш анонимный метод, который принимает один параметр с именем x, который в свою очередь вызывает Facade.Customers.GetSingle с этим параметром.Это перенаправление не имеет никакой пользы, поэтому ReSharper советует вам использовать первую альтернативу.

13 голосов
/ 12 июля 2011

За кулисами компилятор генерирует намного больше кода, если вы используете лямбда-выражение. С помощью группы методов он просто создает нового делегата, указывающего на этот метод:

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

С помощью лямбда-выражения в классе создается анонимный метод (<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>)
2 голосов
/ 12 июля 2011

Если ваш Method1<Guid, BECustomer> принимает аргумент Func<Guid, BECustomer>, Func<Guid, BECustomer> является синонимом:

public delegate BECustomer Func(Guid arg);

На самом деле все Func - это обобщенный делегат:

public delegate TResult Func<T, TResult>(T arg);

Компилятор может проанализировать ваш код и определить, что ваш Func<Guid, BECustomer> совместим с группой методов для Facade.Customers.GetSingle, поскольку подпись метода совпадает с подписью делегата.

Это синтаксический сахар и еще один пример того, как компилятор выполняет за вас всю тяжелую работу.

...