2009-11-11 74 views
5
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);从链中移除代表。这并不明显。从链中删除代表

+5

问题是什么? – Konamiman 2009-11-11 08:29:06

回答

12

委托是不可变的,这意味着你不能改变它。任何似乎改变它的方法,比如“增加”或从它中减去,实际上都会返回一个新的委托。

所以这是行不通的:

a.Remove(b); 

但这:

a = a.Remove(b); 

在调用删除方法是条款。

注意以下语法做正确的事:

a -= b; 

这就是为什么,要求删除,你仍然观察代码调用委托你看似删除后,你还叫原来的委托与该代表出席。

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]