Удаление делегатов из цепочки - PullRequest
5 голосов
/ 11 ноября 2009
class Program
{
    internal delegate int CallBack(int i);

    static void Main(string[] args)
    {
        CallBack callbackMethodsChain = null;
        CallBack cbM1 = new CallBack(FirstMethod);
        CallBack cbM2 = new CallBack(SecondMethod);

        callbackMethodsChain += cbM1;
        callbackMethodsChain += cbM2;

        Delegate.Remove(callbackMethodsChain, cbM1);
    /*L_0039: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class  [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
        L_003e: pop 
        L_003f: ldloc.0 */

        Trace.WriteLine(callbackMethodsChain.GetInvocationList().Length);
        //Output: 2 **WTF!!!**


        callbackMethodsChain -= cbM1;
        /*
    L_0054: call class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class   [mscorlib]System.Delegate, class [mscorlib]System.Delegate)
          L_0059: castclass Generics.Program/CallBack
          L_005e: stloc.0 
          L_005f: ldloc.0 
        */
        Trace.WriteLine(callbackMethodsChain.GetInvocationList().Length);
        //Output: 1
    }

    private static int FirstMethod(int test)
    {            
        Trace.WriteLine("FirstMethod");
        return test;
    }

    private static int SecondMethod(int test)
    {
        Trace.WriteLine("SecondMethod");
        return test;
    }
}

Итак, нам всегда нужно привести (CallBack) Delegate.Remove (callbackMethodsChain, cbM1); удалить делегата из цепочки. Это не очевидно.

Ответы [ 2 ]

12 голосов
/ 11 ноября 2009

Делегат является неизменным, что означает, что вы не можете его изменить. Любые методы, которые, кажется, изменяют его, такие как «добавление» к нему или «вычитание» из него, фактически возвращают новый делегат с изменениями.

Так что это не будет работать:

a.Remove(b);

Но это будет:

a = a.Remove(b);

с точки зрения вызова метода Remove.

Обратите внимание, что следующий синтаксис работает правильно:

a -= b;

Вот почему после вызова Remove вы все еще наблюдаете код, вызывающий делегата, которого вы, казалось бы, удалили, вы все еще вызываете исходную цепочку делегатов с этим делегатом.

1 голос
/ 11 ноября 2009

Некоторые другие пункты

Дубликаты разрешены в вашем т. е. ваш делегат может есть что-то вроде [CbM1, cbM2, cbM2, cbM3]

Если у вас есть группа методов [cbM1, cbM2, cbM3, cbM4, cbM5, cbM1, cbM2] и вы выполнить какую-то операцию, например [CbM1, cbM2, cbM3, cbM4, cbM5, cbM1, cbM2] - [cbM1, cbM2] тогда вы получите [cbM1, cbM2, cbM3, cbM4, cbM5]

Если у вас есть [cbM1, cbM2, cbM3, cbM4, cbM5] и вы выполняете некоторые операции, такие как [cbM1, cbM2 cbM3, cbM4, cbM5] - [cbM1, cbM5] вы получите [cbM1, cbM2, cbM3, cbM4, cbM5]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...