Perché gli eventi non come campi sono implementati come elenco di delegati?

3

tl; dr: Perché gli eventi di tipo campo sono implementati come un singolo campo delegato? Non sarebbe più semplice usare un elenco di delegati, eliminando così il caso speciale null ed evitando tutte le magie di MulticastDelegate?

Il solito schema per aumentare gli eventi di tipo campo (ignorando i problemi di sincronizzazione per il momento) è

if (MyEvent != null)
    MyEvent(this, e);

che può essere abbastanza confuso ( Perché ho un controllo nullo per 0 gestori, ma nessun ciclo per più gestori? ), finché non capisci come vengono implementati eventi simili a campi e che MyEvent fa riferimento a un campo di backup automatico che può contenere null , un singolo delegato o < a href="https://msdn.microsoft.com/en-us/library/ms173172.aspx"> un MulticastDelegate contenente riferimenti a più gestori .

A prima vista, questa sembra essere una strana scelta di design. In particolare, l'alternativa ovvia sarebbe utilizzare un elenco di delegati semplici, che è il modo in cui il pattern Observer è comunemente implementato in linguaggi come Java. È vero, l'invocazione sarebbe leggermente più lunga:

foreach (var handler in MyEvent)
    handler(this, e);

ma sarebbe più facile da capire (secondo la mia opinione soggettiva) e probabilmente più facile da implementare (non c'è bisogno di tutta la logica multicasting delegata).

Ovviamente, i progettisti di C # hanno pensato diversamente. Dal momento che sono un gruppo di persone molto intelligenti, ci deve essere stata una buona ragione per questo. Che cos'è?

    
posta Heinzi 15.03.2015 - 23:28
fonte

2 risposte

1

Tutti i delegati sono effettivamente elenchi. La lista vuota è null , ma puoi ancora aggiungerla con += .

La necessità di controllare null prima di chiamare è molto scomodo, sì. Ma non si verifica perché non sono elenchi! Si verifica a causa di come viene rappresentata la lista vuota.

Tuttavia puoi evitarlo inizializzando l'evento:

public event EventType MyEvent = delegate {};

Vedi anche: link

    
risposta data 15.03.2015 - 23:32
fonte
1

Un uso comune per gli eventi è nei controlli dei moduli. Un controllo del modulo può avere molti eventi, ad esempio un ListView ha 79 eventi diversi.

Dovendo creare un elenco di delegati per ogni evento significherebbe che ce ne sarebbero molti. Con una dozzina di controlli ci sarebbero circa un migliaio di elenchi di delegati da creare, ma la maggior parte di questi finirà inutilizzati e occuperanno solo spazio.

C'è un chiaro vantaggio di avere un modo più leggero di rappresentare un evento non utilizzato. Utilizzando un riferimento null per questo non è necessaria alcuna inizializzazione aggiuntiva per gli eventi, poiché i campi degli oggetti vengono automaticamente impostati sul loro valore predefinito.

Analogamente, vi è il vantaggio di avere eventi separati per il cast singolo e multi-cast e spostare la responsabilità di chiamare i delegati in quelle classi. Un evento non deve essere un elenco quando vi è un solo sottoscrittore (che è il caso più comune), il che rende l'oggetto più piccolo e il processo di chiamata più semplice.

    
risposta data 16.03.2015 - 00:15
fonte

Leggi altre domande sui tag