2016-11-08 23 views
5

將方法添加到現有委託會發生什麼?我的意思是當我將方法1添加到del時,del保留了method1的地址。當我添加method2後,del仍然指向Method1,方法2地址插入到它的底部。這不是說我改變了委託嗎?如果我可以改變這個爲什麼在書中被告知「代表是不變的」?代表是不可改變的,但是如何?

MyDel del = method1; 
del += method2; 
del += method3; 

回答

5

讓我用一個簡單的比喻。int是不變的,所以當你把

int x = 123; 
x += 1; 

實際上就意味着

int _x = x + 1; 
x = _x; 
添加一個當

與代它得到臨時變量_x然後下降初始x_x;在與會代表的情況下

del += method2; 

意味着完全一樣:

delegate _del = delegate.Combine(del, method2); 
del = (MyDel) _del; 
+0

我想你明白我在哪裏掙扎。謝謝 – Lyrk

3
del += method2; 

編譯器變成這樣的事情:

del = (MyDel)Delegate.Combine(del, method2); 

正如你可以看到,新的委託從原始和附加一個(兩者仍然得出不變),然後將結果重新分配給原始委託變量。 (這僅是委託對象本身是不可變的,不是變量/字段引用它。)

相關問題:How does the + operator work for combining delegates?

8

你不改變Delegate對象 - 你」重新改變del以引用不同的對象。

這與字符串完全相同。讓我們轉換代碼爲同樣的事情,但字符串:

string str = "x"; 
str += "y"; 
str += "z"; 

你最終str提到與內容"xyz"一個字符串對象。但是您尚未修改內容爲"x""y""z"的字符串對象。

所以它是與代表。

del += method2; 

相當於:

del = del + method2; 

這相當於:

del = (MyDel) Delegate.Combine(del, method2); 

換言之,「創建具有調用列表指的是現有的兩個代表一個新的委託對象對象」。 (如果delmethod2爲空,則不需要創建新對象。)

有關更多詳細信息,請參閱Delegate.Combine

+0

在你的例子中,str首先持有保存「x」的對象的地址。最後,str保存着包含「xyz」的對象的地址。存儲在str變量中的地址被改變。這不代表我改變了嗎?如果沒有,改變意味着編程中的不同事物? – Lyrk

+0

@Lyrk:'str'的​​值發生變化,所以它指向一個不同的字符串對象。畢竟,你正在執行*賦值* - 你正在設置變量*的值。如果你認爲它是'str = str +「y」',它會讓事情變得更簡單嗎?你認爲表達式「str +」y「'是指什麼?也許你需要閱讀http://jonskeet.uk/csharp/references.html區分varlable(它是一個引用)的值和對象本身是非常重要的。更改變量的值不會修改對象。 –

+0

謝謝你的鏈接... – Lyrk

2

而且換言之另一個版本:以上

MyDelegate delegateOriginal = Method1; 
MyDelegate copyOfOriginal = delegateOriginal; 


Object.ReferenceEquals(printAllhandler, anotherHandler); // return true 

,則返回true,因爲變量delegateOriginalcopyOfOriginal參照相同的實例。

然後

delegateOriginal += Method2; 

如果delegate是可變的一個表達式,然後將返回true,因爲變量將引用同一個對象,但:

Object.ReferenceEquals(printAllhandler, anotherHandler); // return false 

因爲delegate是不可改變的。
delegateOriginal += Method2;將創建委託的新實例並將其引用到原始變量。

相關問題