Action to Delegate : new Action or casting Action?

Hyralex picture Hyralex · May 2, 2013 · Viewed 14.6k times · Source

I found two different ways to initialize a Delegate with an Action :

Create a new action or casting to Action.

Delegate foo = new Action(() => DoNothing(param));
Delegate bar = (Action)(() => DoNothing(param));

Is there a difference between this 2 syntaxes?

Which one is better and why?

Delegate is use in this example because the syntaxes is useful to call methods like BeginInvoke or Invoke with a lambda expression, and it's important to cast the lambda expression into an action

static main 
{
    Invoke((Action)(() => DoNothing())); // OK
    Invoke(new Action(() => DoNothing())); // OK
    Invoke(() => DoNothing()); // Doesn't compil
}

private static void Invoke(Delegate del) { }

But it's interesting to see that the compiler authorized this :

Action action = () => DoNothing();
Invoke(action);

Answer

Hyralex picture Hyralex · May 2, 2013

There is no difference between this two instruction. In the both instruction, a new instance of Action is created.

The IL code below seems to confirm this.

Console Program :

class Program
{
    static void Main(string[] args)
    {
        Delegate barInit = (Action)(() => DoNothing());
        Delegate fooInit = new Action(() => DoNothing());
    }

    private static void DoNothing() { }
}

IL Code :

// First instruction
IL_0000: ldsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate2'
IL_0005: brtrue.s IL_0018

IL_0007: ldnull
IL_0008: ldftn void CodeMachineTest.Program::'<Main>b__0'()

// Create a new Action instance for the instruction (Action)(() => DoNothing())
IL_000e: newobj instance void [mscorlib]System.Action::.ctor(object, native int)

IL_0013: stsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate2'

IL_0018: ldsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate2'
IL_001d: pop

// Second instruction
IL_001e: ldsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate3'
IL_0023: brtrue.s IL_0036

IL_0025: ldnull
IL_0026: ldftn void CodeMachineTest.Program::'<Main>b__1'()
IL_002c: newobj instance void [mscorlib]System.Action::.ctor(object, native int)
IL_0031: stsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate3'

IL_0036: ldsfld class [mscorlib]System.Action CodeMachineTest.Program::'CS$<>9__CachedAnonymousMethodDelegate3'
IL_003b: pop
IL_003c: ret