2015-05-27 35 views
7

Mam następujący kod w mojej klasieCzy można użyć przypisania równości podczas usuwania członków delegatów w metodzie usuwania?

public class Receiver : IReceiver 
{ 

    public event EventHandler Received; 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if (Received != null) 
      { 
       foreach (EventHandler delegateMember in Received.GetInvocationList()) 
       { 
        Received -= delegateMember; 
       } 
      } 
     } 
    } 
} 

Ten kod działa na tym, że kiedy wyrzucać moją klasę wszelkie zdarzenia, które są podłączone do otrzymane razie zostaną usunięte indywidualnie.

Zastanawiałem się, czy zamiast być tak gadatliwy o tym, czy następujące lakoniczne wersja będzie mieć taki sam skutek

protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      Received = null; 
     } 
    } 

Zasadniczo sprowadza się do tego, w jaki sposób przeciążenia operatora zostały stworzone przez Microsoft, gdy wdrażanie przeciążenia uczestników. Wiem, że cała dokumentacja mówi, aby użyć + = do subskrybowania i - = aby zrezygnować z subskrypcji. Widziałem także, że dokument mówi, że zdarzenie zostanie przypisane wartości zerowej, gdy ostatni subskrybent zostanie usunięty. Czego dokumentacja nie mówi, czy przypisanie zdarzenia do wartości null spowoduje anulowanie subskrypcji wszystkich zdarzeń?

Chciałbym wiedzieć, czy jest to możliwe, a jeśli istnieje jakakolwiek dokumentacja, która mówi, że możliwe jest poprawny kod lakoniczny zachowanie.

Aktualizacja:

Robiłem kilka kopanie z kompilatora C# i odkryli, że przypisanie null działa tylko w obrębie klasy, gdy zdarzenie jest zdefiniowane. Funkcje + = i - = są zawsze dostępne zarówno w klasie, jak i poza nią. Prowadzi mnie to do myślenia, że ​​używanie wersji = null jest dopuszczalne. Jest to jednak spekulacja, wciąż nie widziałem żadnej dokumentacji, która stwierdza wyraźnie, że jest to obsługiwana funkcjonalność.

+3

@DStanley Delegaci będą nadal przedstawieniu tych obiektów, tak, ale sam delegat nie będzie już zakorzenione, lub dostępne od korzenia, więc nie byłoby utrzymanie tych obiektów odwołuje żyje. – Servy

+0

Sprawdziłem cicho chwilę przed opublikowaniem pytania. Zasadniczo chodzi o użycie = wersetów za pomocą - =. W MSDN najbliżej znajdującym się na dole tej strony jest https://msdn.microsoft.com/en-us/library/ms366768(v=vs.90).aspx, że null zostanie przypisany, gdy ostatnia instancja programu obsługi zdarzeń jest anulowana. –

Odpowiedz

4

Nie ma powodu, aby nie tylko przypisać null delegatowi tutaj.

Nie można uzyskać w stanie, aby przypisać tylko null, jeśli byłeś poza klasą, która zdefiniowała zdarzenie. Każdemu, kto korzysta z klasy, powinni zajmować się jedynie ich opiekunowie, którzy mogą dodawać lub usuwać. Nie mają oni dostępu do osób obsługujących innych.

Trzeba pamiętać, że delegaci są niezmienne. Korzystanie += na razie nie mutują delegata, aby dodać nową metodę do tego delegata, tworzy nową delegata, że ​​przy wywołaniu, wywołuje zarówno delegatów, które zostały dodane razem. Użycie -= tworzy delegat, który wywołuje wszystkie wywołania pierwszego argumentu operacji, z wyjątkiem drugiego operandu. Dlatego wołając -= w kółko ciągle tworzy się coraz więcej delegatów, z których każdy wciąga coraz mniej rzeczy, aż do momentu, gdy dojdziesz do punktu, w którym delegat już się nie powtarza. Po prostu przypisanie null jest równoznaczne z utworzeniem delegata, który nic nie robi i przypisaniem go bezpośrednio.

Tak więc po wywołaniu -= w kółko nad oryginalnym delegatem, który został przypisany do zdarzenia przed uruchomieniem, istnieje jeszcze N pośrednich delegatów. To powiedziawszy, żaden z delegatów nie może być przywoływany przez żaden element zrootowany, więc wszystkie będą kwalifikowały się do odebrania. Jeśli po prostu przydzielisz null nadal będziesz miał tego samego osieroconego delegata, który był tam pierwotnie, po prostu nie masz już żadnych pośrednich delegatów.

+0

Rozumiem wszystko, co tutaj zamieściłeś, i wiem, że kod skompiluje się w obie strony. Przypuszczam, że kluczową częścią pytania jest ... to - = robienie czegoś innego również, ale = zadanie nie działa? A jeśli tak, to czy możesz być pewien? Jedyne odniesienie, które jest bliskie temu, co do tej pory znalazłem, znajduje się u dołu strony https://msdn.microsoft.com/en-us/library/ms366768(v=vs.90).aspx mówi, aby użyć operatora - =. Mówi, że możesz przetestować wartość zerową, aby sprawdzić, czy są subskrybenci. Nie mówi, że możesz użyć operatora =. –

+0

@ColinDawson Operator '- =' nie robi nic oprócz tworzenia nowego uczestnika, który wyklucza drugi argument operacji z listy wywołań, a następnie przypisuje nowego delegata do pierwszego argumentu operacji. Utworzenie nowego delegata, który nic nie robi (a.k.a. 'null') i przypisanie go bezpośrednio, jest zatem równoważne. Oczywiście, jeśli żadna z procedur obsługi zdarzeń nie odwołuje się do obiektu definiującego zdarzenie (i przeżyje tego odbiorcę), nie ma powodu, aby robić to * albo *, ponieważ cały odbiornik powinien wkrótce przestać być rootowany w pierwszej kolejności. nie ma powodu, aby to anulować. – Servy

+0

Rozumiem, że nie można napisać tego w kodzie, ale czy istnieje jakaś dokumentacja, która obsługuje użycie = null? Chciałbym móc po prostu użyć zwięzłego kodu, ponieważ wygląda to bardzo wyraźnie, ale chcę mieć pewność, że pod maską wszystko działa zgodnie z zamierzeniami - tak samo jak pełny kod z przykładu. To, czego szukam, to cytat, który mówi, że jest to dopuszczalna konstrukcja. Nie chcę zakładać, że to działa. To, co mówisz, ma sens, zrozumiem, jak doszło do tego zrozumienia. –