Search code examples
c#method-group

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


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?


Solution

  • 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.