Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any benefits to using a C# method group if available?

Tags:

When dealing with something like a List<string> you can write the following:

list.ForEach(x => Console.WriteLine(x)); 

or you can use a method group to do the same operation:

list.ForEach(Console.WriteLine); 

I prefer the second line of code because it looks cleaner to me, but are there any benefits to this?

like image 407
Chris Missal Avatar asked Oct 01 '10 18:10

Chris Missal


People also ask

Is it better to use AC or not?

Your AC will actually run longer overall if it is left on all day instead of being shut off. If you turn it off for part of the day, it runs less and results in more energy savings for you. In almost all cases, it will save you money to shut off your AC while you are away from home.


2 Answers

Well, let's take a look and see what happens.

static void MethodGroup() {     new List<string>().ForEach(Console.WriteLine); }  static void LambdaExpression() {     new List<string>().ForEach(x => Console.WriteLine(x)); } 

This gets compiled into the following IL.

.method private hidebysig static void MethodGroup() cil managed {     .maxstack 8     L_0000: newobj instance void [mscorlib]System.Collections.Generic.List`1<string>::.ctor()     L_0005: ldnull      L_0006: ldftn void [mscorlib]System.Console::WriteLine(string)     L_000c: newobj instance void [mscorlib]System.Action`1<string>::.ctor(object, native int)     L_0011: call instance void [mscorlib]System.Collections.Generic.List`1<string>::ForEach(class [mscorlib]System.Action`1<!0>)     L_0016: ret  }  .method private hidebysig static void LambdaExpression() cil managed {     .maxstack 8     L_0000: newobj instance void [mscorlib]System.Collections.Generic.List`1<string>::.ctor()     L_0005: ldsfld class [mscorlib]System.Action`1<string> Sandbox.Program::CS$<>9__CachedAnonymousMethodDelegate1     L_000a: brtrue.s L_001d     L_000c: ldnull      L_000d: ldftn void Sandbox.Program::<LambdaExpression>b__0(string)     L_0013: newobj instance void [mscorlib]System.Action`1<string>::.ctor(object, native int)     L_0018: stsfld class [mscorlib]System.Action`1<string> Sandbox.Program::CS$<>9__CachedAnonymousMethodDelegate1     L_001d: ldsfld class [mscorlib]System.Action`1<string> Sandbox.Program::CS$<>9__CachedAnonymousMethodDelegate1     L_0022: call instance void [mscorlib]System.Collections.Generic.List`1<string>::ForEach(class [mscorlib]System.Action`1<!0>)     L_0027: ret  } 

Notice how the method group approach creates an Action<T> delegate for one time use and the lambda expression approach creates a hidden anonymous delegate field and does an inline initialization of it if necessary. Notice brtrue instruction at IL_000a.

like image 88
Brian Gideon Avatar answered Sep 18 '22 14:09

Brian Gideon


There is an extra level of indirection when using the lambda expression. With a non-closure expression like that, you'll simply have an extra method call in-between, as mentioned by others.

There are a few interesting differences though. In the second case, a new delegate instance is being created on each call. For the former, the delegate is created once and cached as a hidden field, so if you're calling a lot you'll save on allocations.

Additionally, if you introduce a local variable into the lambda expression, it becomes a closure and instead of just a local method being generated, a new class will be created to hold this information, meaning an extra allocation there.

like image 34
MikeP Avatar answered Sep 21 '22 14:09

MikeP