簡體   English   中英

在什么類委托的實例被調用?

[英]On what instance of class delegate gets invoked?

考慮一下這段代碼

public class A
{
     //...
     void f()
     {  
          B b = new B();
          b.SomeEvent += this.SomeMethod;
     }
     void SomeMethod() {}
 }

 public class B
 {
     //...

     public event SomeEventHandler SomeEvent;

     void h()
     {  
          if ( SomeEvent != null )
          {
               SomeEvent.invoke();
          }
     }
 }

在這段代碼片段中, SomeEvent.invoke()實際上調用了A類的SomeMethod() 所以在這一點上,我幾乎沒有問題:

  • 在什么實例的ASomeMethod被調用? B如何知道要調用委托的實例? CLR如何在這里工作?
  • 另外, SomeMethod是一個私有方法,那么為什么B能夠從A類外部調用這個方法呢?

編輯:

在閱讀了前幾個答案之后,我開始知道Delegate有一個Target屬性,在該屬性上調用了委托。 但我真的不明白這個Target屬性到底是什么步驟? 是誰設定的? 當我寫b.SomeEvent += this.SomeMethod; ,它是否也設置了Target屬性? 究竟怎么樣?

 b.SomeEvent += this.SomeMethod

這里有很多糖會阻止你看到真正發生的事情。 寫出來,它類似於:

 b.SomeEvent.add(new MulticastDelegate(this, SomeMethod));     // not legal code

其中add()是事件的add訪問器,當您沒有顯式聲明自己的訪問器時,編譯器會自動生成一個。 委托構造函數的第一個參數是您要詢問的對象實例,即委托對象的Target屬性。 請注意,這會產生副作用,事件訂閱會保留對b對象的引用。 這可以防止它被垃圾收集,這在調用事件時會相當糟糕。

這也可能是一個問題,你可以無意中泄漏對象引用。 在代碼中沒有好的方法來取消訂閱事件處理程序,因此只要你調用h()的B對象,A對象就會生存。

委托包含調用方法的目標引用。 您可以使用Delegate.Target屬性進行檢查。 在這種情況下,它將在調用f的實例上調用。 (如果您正在調用靜態方法,則為null。)

至於隱私 - 這只是代表的一個特點。 您只能在有權訪問私有方法的代碼中創建委托,但您可以任何地方運行它。 可以認為這就像通過從公共接口實現調用私有方法來實現接口一樣。

在什么實例的A,SomeMethod被調用? B如何知道要調用委托的實例? CLR如何在這里工作?

委托實際上包含對實際實例的引用。 這將導致它在調用它的特定實例上調用。

另外,SomeMethod是一個私有方法,那么為什么B能夠從A類外部調用這個方法呢?

它不直接執行方法 - 它執行委托 這里有一點不同 - 私有約束僅適用於該方法,但由於類本身創建了委托,因此它可以訪問該方法,因此一切正常。

  • 無論在附加到事件時使用了什么實例
  • 因為A在類之外傳遞了委托表示。

特定的Delegate實例具有Target屬性; 這表示調用委托時將使用的實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM