2011-03-25 84 views
5

考慮以下代碼,什麼類的委託被調用?

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()實際上調用ASomeMethod()。所以在這一點上,我有幾個問題:

  • 什麼樣的ASomeMethod被調用? B如何知道要調用委託的實例? CLR如何在這裏工作?
  • 另外,SomeMethod是一個私人方法,那麼B怎麼能夠從類A以外調用此方法?

編輯:

閱讀前幾個答案後,我才知道,Delegate有其代表被調用的Target屬性。但我無法真正理解這個Target屬性設置的步驟?誰設定的?當我寫b.SomeEvent += this.SomeMethod;時,它是否也設置了Target屬性?究竟如何?

回答

2
b.SomeEvent += this.SomeMethod 

這裏有很多糖,可以防止看到真正發生的情況。寫出來,它類似於此:

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

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

這也可能是一個問題,可以無意中泄漏對象的引用。在您的代碼中沒有好的方法來取消訂閱事件處理程序,因此A對象將與您在其中調用h()的B對象一樣長。

+0

最後一篇文章...這告訴我我正在尋找的東西。 +1 – Nawaz 2011-03-25 19:47:20

1
  • 無論實例被附接至所述事件
  • 當由於A通過委託表示給它的類以外使用。

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

2

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

至於隱私 - 這只是代表的特徵之一。你只能在裏面創建這個委託代碼裏面有一個私有方法,但是你可以在裏運行它在任何地方。認爲這就像通過從公共接口實現中調用私有方法來實現接口一樣。

+0

喬恩:我編輯了我的問題。請參閱編輯。我想深入瞭解它。 – Nawaz 2011-03-25 18:52:22

+0

順便說一句,我已經買了你的書,可能你記得我曾經告訴過你,當我命令它。所以,如果你在書中討論過這個問題,請告訴我這一章節,以便我自己仔細閱讀。 – Nawaz 2011-03-25 18:54:05

+0

@Nawaz:第2章包含了很多與會代表,是的。享受:) – 2011-03-25 19:00:49

2

A,SomeMethod被調用的是什麼實例? B如何知道要調用委託的實例? CLR如何在這裏工作?

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

此外,SomeMethod是一個私有方法,那麼B怎麼能夠從類A外部調用這個方法呢?

它不直接執行該方法 - 它執行委託代理。這裏有一個區別 - 私有約束只適用於該方法,但由於類本身創建委託,它有權訪問該方法,所以一切正常。

相關問題