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);从链中删除委托。这显然不是。
答案 0 :(得分:12)
委托是不可变的,这意味着你无法改变它。任何似乎改变它的方法,比如“添加”它或“从中减去”,实际上会返回一个带有更改的新委托。
所以这不起作用:
a.Remove(b);
但这会:
a = a.Remove(b);
就调用Remove方法而言。
请注意,以下语法是正确的:
a -= b;
这就是为什么在调用Remove之后,你仍然会观察调用你看似被删除的委托的代码,你仍然会调用原来的代理链,并且该代表在场。
答案 1 :(得分:1)
其他一些观点
允许重复 代表,即你的代表可以 有类似的东西 [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]