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;
}
}
Run Code Online (Sandbox Code Playgroud)
所以,我们总是需要强制转换(CallBack)Delegate.Remove(callbackMethodsChain,cbM1); 从链中删除委托.这显然不是.
ang*_*son 12
委托是不可变的,这意味着您无法更改它.任何似乎改变它的方法,比如"添加"它或"从中减去",实际上会返回一个包含更改的新委托.
所以这不起作用:
a.Remove(b);
Run Code Online (Sandbox Code Playgroud)
但这会:
a = a.Remove(b);
Run Code Online (Sandbox Code Playgroud)
在调用Remove方法方面.
请注意,以下语法正确的做法:
a -= b;
Run Code Online (Sandbox Code Playgroud)
这就是为什么在调用Remove之后,你仍然会观察到调用你看似被删除的委托的代码,你仍然会调用原来的委托链.