2010-10-15 12 views
25

Biorąc pod uwagę poniższy kod:Inwokacja polimorficznego pola podobnego zdarzenia

public class TableMain { 
    public virtual event Action UpdateFilter; 
    .... 
} 

public class TableSub : TableMain { 
    public override event Action UpdateFilter; 

    public void UpdateQuery() { 
     ..... 
     if (UpdateFilter!=null) { 
       UpdateFilter(); // Invocation of polymorphic field-like event??? 
     } 
    } 
} 

W tym kodzie ReSharper pokazuje alert „wezwaniem polimorficznych imprezy polu-like”.

Moje pytanie brzmi: Co to właściwie oznacza? I czy jest to ostrzeżenie dla złej praktyki programistycznej? Ponadto, czy złą praktyką jest polimorficzne wywołanie zdarzenia? (Wiedząc, że zdarzenie może zostać podniesione tylko z klasy, która go zadeklarowała.)

Odpowiedz

41

Cóż, faktycznie masz dwa zdarzenia polowe podobne do tutaj. Twoje zastąpienie spowoduje przesłonięcie części dodaj/usuń, ale będziesz mieć dwa pola - jeden w TableMain i jeden w TableSub. Tylko ten w TableSub nigdy nie będzie wartością NULL, chyba że wartość zostanie ustawiona jawnie w TableMain ... więc jeśli TableMain kiedykolwiek spróbuje podnieść samo zdarzenie, nie wywoła tego samego zestawu procedur obsługi, jak w przypadku TableSub. Zasadniczo zachowuje się dziwnie.

Odpowiednie podejście jest dostarczenie zabezpieczonego sposób, aby umożliwić w TableMain zdarzenie być podniesione przez podklasy:

protected void OnUpdateFilter() 
{ 
    Action handler = UpdateFilter; 
    if (handler != null) 
    { 
     handler(); 
    } 
} 

Następnie należy zdarzenie bez wirtualnego i usunąć wymuszenie w TableSub.

Pamiętaj, że sygnatura Twojego wydarzenia nie pasuje do zwykłej konwencji dotyczącej wydarzeń - jakikolwiek powód nie używania EventHandler?

+0

To brzmi jak duże potencjalne źródło błędu dla mnie, ponieważ najprawdopodobniej nie jest to, czego można się spodziewać podczas pisania takiego kodu. Nigdy wcześniej nie musiałem myśleć o tym konkretnym aspekcie. Czy wiesz, dlaczego mimo to zdarzenia wirtualne są syntaktycznie akceptowane? –

+1

@John. Odnośnie --- "Zauważ, że twój podpis zdarzenia nie pasuje do zwykłej konwencji dla zdarzeń - jakikolwiek powód nie używania EventHandler?" Korzystam tylko z istniejącego delegata "Działania", ponieważ w tym przypadku nie potrzebuję żadnych argumentów (obiekt, zdarzenia) w subskrybentach tego wydarzenia. Czy to (znowu) kiepska praktyka programowania? Czy lepiej jest utworzyć oddzielnego (pustego) delegata dla tej sprawy? –

+1

@Thomas: Są sposoby, którymi możesz * rozsądnie korzystać z nich - na przykład, możesz zalogować każdą subskrypcję, a następnie przekazać ją do wdrożenia podstawowego. Musisz też mieć możliwość efektywnego abstrakcji, aby móc umieścić je w interfejsach. –

Powiązane problemy