![](/img/trans.png)
[英]Passing delegate declaration to a class and then later changing its value to be invoked
[英]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()
。 所以在這一點上,我幾乎沒有問題:
A
, SomeMethod
被調用? 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.