Podczas programowania zdarzeń w języku C # zaleca się utworzenie delegata w postaci:
delegate XEventHandler(object sender, XEventArgs e);
Moje pytanie jest na pierwszym argumencie delegata object sender
. Czy zawsze musi być ogólny object
? Posiadanie nadawcy typu object
zawsze skutkuje kodem podobnym do tego.
val = ((ConcreteType)sender).Property;
lub jeszcze bardziej gadatliwy
ConcreteType obj = sender as ConcreteType
if (obj != null) { ... }
Jednym argumentem przeciwko nadawcom o silnym typie jest to, że inne obiekty mogą przekazywać zdarzenie bez obawy o typ. Chociaż może to mieć sens w środowiskach GUI, nie jestem pewien, czy mogłoby to przynieść korzyści poza GUI.
Co się stanie, jeśli klasa nadawcy jest zawsze znana (przynajmniej jako klasa abstrakcyjna)? Na przykład, jeśli mam wdrożenia ListChanged
zdarzenie w abstrakcyjnej List
klasy, a jeśli inne klasy będą dziedziczyć go (np LinkedList
, ArrayList
), to wszystko jest w porządku, aby określić mój delegata z nadajnikiem typu List
?
delegate ListChangedEventHander(List sender, ListChangedEventArgs e);
Czy może miałoby to negatywne skutki zmiany modelu konwencjonalnego object sender
na bardziej konkretny?
System.Windows.Forms
przestrzeń nazw jest miejsce, gdzie są najbardziej intensywnie używane imprezy, i uczynił to sens, aby zapisać się naClick
wypadekButton
lubCheckBox
. Dlatego nadawca musi być ogólny. ...List
s.Powodem tego zalecenia jest to, że umożliwia przyszłe zmiany, które niekoniecznie wymagają zmian w istniejącym kodzie, a zwłaszcza w interfejsie publicznym.
Sam mechanizm zdarzenia może być nadal używany w przypadku zdarzeń w stylu „VB6”, ale będziesz musiał zmienić wszystkich istniejących klientów, jeśli kiedykolwiek będziesz musiał zmienić podpis (lub gorzej: utwórz nowe wersje tych samych zdarzeń). Przy zalecanym podejściu, o ile nowsze elementy dziedziczą po istniejących, możesz zaktualizować podpis bez poprawiania istniejącego kodu.
źródło