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;
}
}
So, we always need to cast (CallBack)Delegate.Remove(callbackMethodsChain, cbM1); to remove delegate from chain. It's not obviously.