Informazioni sulla struttura dei delegati in C #

2

Ho cercato di capire i delegati di C # utilizzando Pro C # 5 .

In breve, l'autore descrive la motivazione per i delegati come un modo strutturato di trattare i puntatori di funzione e le richiamate o la comunicazione bidirezionale tra gli oggetti.

La parte che trovo confusa è la sintassi / implementazione per questo:

  • Da un lato, un oggetto di tipo delegato è visto come gestore o il responsabile per invocare un metodo o un elenco di metodi. A tal fine, ha metodi come Invoke() ecc.

  • D'altra parte, il tipo delegato viene usato come un "wrapper" con per passare i metodi.

Ad esempio, mi sembra strano che una chiamata al GetInvocationList() di un delegato restituisca un array di delegati. Non dovrebbe esserci qualcos'altro con cui avvolgere i metodi?

Mi aspettavo che ci fosse qualche altro costrutto / tipo, ad esempio MethodContainer che avvolge i metodi. Quindi la sintassi per l'aggiunta di metodi a un delegato sarebbe

class MyClass{ void Method(string s){} }

MyClass c = new MyClass();
MethodContainer container = new MethodContainer(c.Method);

delegate void MyDelegate(string s);
MyDelegate d = new MyDelegate();

d.Add(container);

d.GetInvocationList(); // returns array of MethodContainer
    
posta Isaac Kleinman 09.09.2014 - 21:55
fonte

2 risposte

4

In realtà è questo tipo di distinzione fatta sotto le copertine. Delegate è il wrapper a funzione singola e MulticastDelegate è il tipo che è la forma composta di Delegate . La parte confusa è che Delegate non è realmente esposto dalle viscere del runtime. Tutti i delegati creati da C # sono delegati multicast, anche se contengono solo un singolo elemento.

Questo perché storicamente i delegati erano in gran parte presenti per far funzionare bene gli eventi di Windows, che spesso avrebbero più ascoltatori. Ora che i delegati sono usati di più per approcci di programmazione funzionale, in teoria è un po 'più scomodo. In pratica, pochissime persone usano la funzionalità multicast al di fuori degli eventi dati i suoi aspetti negativi (eccezioni in qualsiasi punto della catena lo infrangeranno, e il chiamante non saprà dove, difficile eseguire il debug) e perché non è esattamente noto.

    
risposta data 09.09.2014 - 22:37
fonte
0

Hai ragione è un po 'confuso.

Nel progetto .net iniziale, si supponeva che un Delegate fosse un "metodo di riferimento" a un metodo di destinazione singolo e un MulticastDelegate doveva essere un contenitore che poteva contenere un numero variabile di delegati e li invoca come batch.

Tuttavia, prima del rilascio di .net 1.0 era deciso di unire la funzionalità di Delegate e MulticastDelegate , in modo che ogni delegato sia effettivamente un'istanza di MulticastDelegate , indipendentemente dal fatto che abbia uno o più target. Apparentemente non è stato possibile ripulire l'API dopo questa modifica, quindi ora abbiamo un'API un po 'confusa.

Ad esempio, un delegato ha la proprietà Target che ha un riferimento al metodo da richiamare. Ma nel caso di un delegato con più bersagli, questa proprietà restituisce solo uno dei bersagli casuali.

Il metodo GetInvocationList() confonde per lo stesso motivo. Si suppone che restituisca una matrice di tutti gli obiettivi in un delegato. Poiché non esiste un tipo separato per i delegati a target singolo, deve restituire un array di MulticastDelegate s, un MulticastDelegate per ciascun target. Nel caso di un delegato a target singolo, restituisce semplicemente un array con un elemento che è il delegato originale stesso.

    
risposta data 02.07.2015 - 16:51
fonte

Leggi altre domande sui tag