Akcja vs delegat event
Widziałem deweloperów używających poniższych kodów całkiem alternatywnie. Jaka jest dokładna różnica między nimi, a które z nich są zgodne ze standardem? Są takie same, jak Action
i {[3] } jest również delegatem:
public event Action<EmployeeEventAgs> OnLeave;
public void Leave()
{
OnLeave(new EmployeeEventAgs(this.ID));
}
VS
public delegate void GoOnLeave(EmployeeEventAgs e);
public event GoOnLeave OnLeave;
public void Leave()
{
OnLeave(new EmployeeEventAgs(this.ID));
}
8 answers
Fwiw, żaden z przykładów nie używa standardowych konwencji. NET. RodzajnikEventHandler<T>
powinien zadeklarować Zdarzenie:
public event EventHandler<EmployeeEventArgs> Leave;
Przedrostek " On " powinien być zarezerwowany dla metody chronionej, która wywołuje zdarzenie:
protected virtual void OnLeave(EmployeeEventArgs e) {
var handler = Leave;
if (handler != null) handler(this, e);
}
Nie masz , aby zrobić to w ten sposób, ale każdy natychmiast rozpozna wzór, zrozumie Twój kod i wie, jak go używać i dostosowywać.
I ma wielką zaletę, że nie jest zmuszony do wyboru pomiędzy deklaracją niestandardowego delegata i Action<>
, To najlepszy sposób. Co odpowiada na twoje pytanie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-05 09:01:51
Następujące dwie linijki kodu są prawie równoważne:
public event Action<EmployeeEventAgs> Leave;
W porównaniu do:
public event EventHandler<EmployeeEventAgs> Leave;
Różnica polega na podpisie metody obsługi zdarzenia. Jeśli użyjesz pierwszego podejścia z akcją, możesz mieć:
public void LeaveHandler(EmployeeEventAgs e) { ... }
A potem to:
obj.Leave += LeaveHandler;
Przy drugim podejściu podpis LeaveHandler
musi być inny:
public void LeaveHandler(object sender, EmployeeEventAgs e) { ... }
Jest to bardzo ważne , aby zauważyć, że w obu przypadkach słowo kluczowe event
jest używane do zadeklaruj członka wydarzenia. Członek zdarzenia zadeklarowany w ten sposób nie jest po prostu polem klasy, mimo że wygląda tak, jakby nim był. Zamiast tego kompilator tworzy ją jako właściwość zdarzenia 1. Właściwości zdarzenia są podobne do zwykłych właściwości, z tym wyjątkiem, że nie mają dostępu get
ani set
. Kompilator pozwala na ich użycie tylko po lewej stronie przydziałów +=
i -=
(dodawanie lub usuwanie obsługi zdarzenia). Nie ma sposobu, aby nadpisać już przypisane procedury obsługi zdarzeń, lub wywołują Zdarzenie poza klasą deklarującą.
Jeśli w obu przykładach brakowało słowa kluczowego event, można wykonać następujące operacje bez błędu lub ostrzeżenia:
obj.Leave = LeaveHandler;
Który usunie wszystkie zarejestrowane programy obsługi i zastąpi je LeaveHandler
.
Dodatkowo, możesz również wykonać to wywołanie:
obj.Leave(new EmployeeEventAgs());
Dwie powyższe sytuacje są uważane za anty-wzorzec , jeśli zamierzasz aby utworzyć wydarzenie. Zdarzenie powinno być wywoływane tylko przez obiekt właściciela i nie powinno pozwalać na niewykrywalne usunięcie subskrybentów. Słowo kluczowe event
jest konstrukcją programistyczną. NET, która pomaga trzymać się prawidłowego użycia zdarzeń.
Mając powyższe na uwadze, wierzę, że wiele osób trzyma się podejścia EventHandler
, ponieważ jest bardziej mało prawdopodobne, aby użyć EventHandler
bez słowa kluczowego event
. Działania mają szerszy zakres zastosowania, nie wyglądają tak naturalnie, gdy używane jako wydarzenia. Ta ostatnia jest oczywiście osobistą opinią, ponieważ podejście do obsługi zdarzeń stało się prawdopodobnie zbyt sztywne w moich własnych praktykach kodowania. Mimo to, jeśli działania są właściwie wykorzystywane, nie jest przestępstwem ich wykorzystanie do wydarzeń.
1 właściwość event jest tym, co kompilator automatycznie generuje, gdy widzi kod w ten sposób:
event EventHandler SomeEvent
Staje się mniej więcej tym samym kodem, co następujący:
private EventHandler _someEvent; // notice the lack of the event keyword!
public event EventHandler SomeEvent
{
add { _someEvent += value; }
remove { _someEvent -= value; }
}
Wywołania zdarzeń, które zapisujemy jako to:
this.SomeEvent(sender, args);
Są zamieniane na to:
this._someEvent(sender, args);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-04 06:57:14
Action<T>
jest dokładnie taki sam jak delegate void ... (T t)
Func<T>
jest dokładnie taki sam jak delegate T ... ()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-15 18:54:46
Action jest tylko skrótem do pełnej deklaracji delegata.
public delegate void Action<T>(T obj)
Http://msdn.microsoft.com/en-us/library/018hxwa8.aspx
Który z nich będzie używany zależy od standardów/stylu kodowania Twojej organizacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-15 18:54:09
Tak, Action i Func są po prostu wygodnymi delegatami zdefiniowanymi w clr 3.5.
Action, Func i Lambda to tylko cukier składniowy i wygoda w używaniu delegatów.
Nie ma w nich nic magicznego. Kilka osób napisało proste biblioteki dodatków 2.0, aby dodać tę funkcjonalność do kodu 2.0.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-17 16:41:03
Możesz zajrzeć tutaj, najlepszym opisem jest sprawdzenie, co kompilator faktycznie generuje dla akcji. Nie ma różnicy funkcjonalnej w tym co napisałeś, tylko krótsza, wygodniejsza składnia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:32:32
Ogólnie są równoważne. Jednak w kontekście użycia delegata dla typu zdarzenia, konwencją jest użycie EventHandler (gdzie T dziedziczy EventArgs):
public event EventHandler<EmployeeEventArgs> Left;
public void Leave()
{
OnLeft(this.ID);
}
protected virtual void OnLeft(int id)
{
if (Left != null) {
Left(new EmployeeEventArgs(id));
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-17 17:09:38
Mogłeś sam napisać te akcje i Func generic, ale ponieważ są one ogólnie użyteczne, napisali je za Ciebie i umieścili w bibliotekach. Net.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-17 18:57:42