不调用空委托吗?

时间:2010-07-29 09:46:45

标签: .net delegates virtual-machine

在.NET中,当你有一个只有一个空方法的委托订阅它时,.NET VM是否意识到这一点并且甚至不会调用它?

我问,因为我注意到,当您订阅一次时,调用计数设置为2,但是当您取消订阅时,该值将下降到0(而不是1)。

3 个答案:

答案 0 :(得分:5)

不,你看到的是MulticastDelegate类,它优化了只有一个目标方法的一般情况。只有一个,它可以将目标存储在基类'(Delegate)_methodBase和_target字段中。

当存在多个目标时,必须创建一个列表来存储目标。现在它使用_invocationList字段,因此它可以根据需要存储任意数量的目标。换句话说,_invocationCount将从不为1。

您可以通过在调试器中扩展“base”来看到这一点。

答案 1 :(得分:2)

不,就我所知,仍然会调用一个空的但非空的委托。

关于您的取消订阅:请提供一些示例代码。 (我将在一分钟内提供显示相反的示例代码。)

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");
    }
}

这只打印1次 - 在订阅/取消订阅周期之前和之后显示一个“空”处理程序。

我确信当您发布一个显示您的意思的类似示例时,我们将能够轻松地解释您的结果。

答案 2 :(得分:0)

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

输出:

1
2
Subscriber2
1