tags:

views:

50

answers:

3

Hi,

In .NET, when you have a delegate that only has an empty method subscribed to it, does the .NET VM realize this and skip even calling it?

I'm asking because I noticed that the invocation count is set to 2 when you subscribe once but when you unsubscribe it, the value goes down to 0 (not 1).

Thanks in advance.
Daisuke

+1  A: 

No, an empty but non-null delegate will still be invoked as far as I'm aware.

Regarding your unsubscription: please provide some sample code. (I'll provide sample code showing the reverse in a minute.)

using System;

class Test
{
    static void Main()
    {
        Action action = EmptyMethod;
        Console.WriteLine(action.GetInvocationList().Length);        
        action += NonEmptyMethod;
        action -= NonEmptyMethod;
        Console.WriteLine(action.GetInvocationList().Length);        
    }

    static void EmptyMethod() {}

    static void NonEmptyMethod()
    {
        Console.WriteLine("Testing");
    }
}

This just prints 1 twice - showing a single "empty" handler before and after the subscribe/unsubscribe cycle.

I'm sure that when you've posted a similar example which shows what you mean, we'll be able to explain your results easily.

Jon Skeet
Skeeted once again :) ... congrats on the 200K - Inspirational.
Gishu
@Gishu: I'm not at 200K just yet. Another 166 to go. I suspect that will happen tomorrow...
Jon Skeet
A: 
EventHandler del = null;
EventHandler subscriber2 = delegate { Console.WriteLine("Subscriber2");};
del += delegate { };
Console.WriteLine(del.GetInvocationList().Length);
del += subscriber2;
Console.WriteLine(del.GetInvocationList().Length);

del(null, null);

del -= subscriber2;
Console.WriteLine(del.GetInvocationList().Length);

Output:

1
2
Subscriber2
1
Gishu
+4  A: 

No, what you are seeing is the MulticastDelegate class optimizing the general case in which there's only one target method. With just one, it can store the target in the base class' (Delegate) _methodBase and _target fields.

When there's more than one then it has to create a list to store the targets. Now it uses its _invocationList field so it can store as many targets as needed. In other words, _invocationCount will never be 1.

You can see this by expanding "base" in the debugger.

Hans Passant
Ah, the joys of misinterpreting internal field values. Computing the invocation count via `GetInvocationList()` *does* return 1, of course :)
Jon Skeet