2016-11-08 21 views
5

Co stanie się, gdy dodaję metodę do istniejącego pełnomocnika? Mam na myśli, kiedy dodałem metodę 1 do del, del przechowuje adres metody1. Kiedy dodam metodę2, del nadal wskazuje na metodę 1, a adres metody 2 jest wstawiony na dole. Czy to nie znaczy, że zmieniłem delegata? Jeśli mogę to zmienić, dlaczego w książkach mówi się "delegaci są niezmienni"?Delegaci są niezmienne, ale jak?

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

Odpowiedz

5

Pozwól mi użyć prostej analogii.int jest niezmienna, więc kiedy można umieścić

int x = 123; 
x += 1; 

to faktycznie oznacza

int _x = x + 1; 
x = _x; 

podczas dodawania jednego masz nowy tymczasowa zmienna _x a następnie spadek początkową x przez zastępując go _x; w przypadku delegatów

del += method2; 

oznacza to samo:

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

Myślę, że rozumiesz, gdzie walczę. Dzięki – Lyrk

3
del += method2; 

kompilator zamienia to na coś takiego:

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

Jak widać, nowy delegat wywodzi się z pierwotnego i dodatkowego jednego (z których oba pozostają bez zmian), a następnie wynik jest ponownie przypisywany do oryginalnej zmiennej delegowanej. (To jest tylko sam obiekt delegat, który jest niezmienny, nie zmienna/pole przedstawieniu go.)

pokrewne pytanie:How does the + operator work for combining delegates?

8

Nie zmieniamy obiekt Delegate - ty” zmienia się del, aby odnieść się do innego obiektu.

To dokładnie to samo, co w przypadku ciągów. Załóżmy, zamienić kod do tego samego, ale z ciągów:

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

skończyć z str odnosząc się do obiektu String z zawartością "xyz". Ale nie zmodyfikowano obiektów ciągów o zawartości "x", "y" lub .

Podobnie jest z delegatami.

del += method2; 

odpowiada:

del = del + method2; 

co jest równoważne:

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

Innymi słowy, „utworzyć nowy obiekt delegata, który ma list procedury wywołania nawiązujące do istniejących dwóch delegata obiekty ". (Jeśli albo del lub method2 ma wartość null, nie trzeba tworzyć nowego obiektu.)

Więcej informacji na ten temat można znaleźć w artykule Delegate.Combine.

+0

W twoim przykładzie, str trzymał adres obiektu, który na początku ma "x". Na końcu str przytrzymuje adres obiektu zawierającego "xyz". Adres zapisany w zmiennej str zostanie zmieniony. Czy to nie znaczy, że zmieniłem str? Jeśli nie, zmiana oznacza inną rzecz w programowaniu? – Lyrk

+0

@Lyrk: Wartość 'str' zmienia się tak, że odnosi się do innego obiektu typu string. W końcu wykonujesz * zadanie * - ustawiasz * wartość zmiennej *. Czy to sprawia, że ​​rzeczy prostsze dla ciebie, jeśli uważasz to za "str = str +" y "'? Jak myślisz, do czego odnosi się wyrażenie "str +" y ""? Być może musisz przeczytać http://jonskeet.uk/csharp/references.html Naprawdę ważne jest rozróżnienie między wartością zmiennej (która jest referencją) a samym obiektem. Zmiana wartości zmiennej nie modyfikuje obiektu. –

+0

dziękuję za link ... – Lyrk

2

I kolejna wersja innymi słowy:

MyDelegate delegateOriginal = Method1; 
MyDelegate copyOfOriginal = delegateOriginal; 


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

Powrót prawda powyżej ponieważ zmiennych delegateOriginal i copyOfOriginal odniesieniu do tej samej instancji .

Następnie

delegateOriginal += Method2; 

Jeśli delegate był zmienny następny wyraz następnie zwróci true, ponieważ zmienne będą odwoływać się do tego samego obiektu, ale:

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

Ponieważ delegate jest niezmienna.
Linia delegateOriginal += Method2; utworzy nową instancję delegata i umieści ją jako odniesienie do oryginalnej zmiennej.

Powiązane problemy