Domanda

Supponiamo di avere:

interface Foo 
{
 bool Func(int x);
}

class Bar: Foo
{
  bool Func(int x)
  {
   return (x>0);
  }  
}

class Baz: Foo
{
  bool Func(int x)
  {
   return (x<0);
  }  
}

Ora possiamo girare Bar e Baz come Foos e chiamare i loro metodi Func.

I delegati semplificano un po’ il tutto:

delegate bool Foo(int x);

bool Bar(int x)
{
 return (x<0);
}

bool Baz(int x)
{
 return (x>0);
}

Ora possiamo mettere in giro Bar e Baz come delegati Foo.

Qual è il vero vantaggio dei delegati, oltre a ottenere un codice più breve?

È stato utile?

Soluzione

C'è una leggera differenza: i delegati possono accedere alle variabili membro delle classi in cui sono definiti.In C# (a differenza di Java) tutte le classi interne sono considerate statiche.Pertanto se stai utilizzando un'interfaccia per gestire una richiamata, ad es.un ActionListener per un pulsante.Alla classe interna implementata devono essere passati (tramite il costruttore) i riferimenti alle parti della classe contenitore con cui potrebbe dover interagire durante il callback.I delegati non hanno questa restrizione quindi riduce la quantità di codice richiesto per implementare la richiamata.

Anche un codice più breve e conciso rappresenta un degno vantaggio.

Altri suggerimenti

Dal punto di vista dell'ingegneria del software hai ragione, i delegati sono molto simili alle interfacce di funzioni in quanto prototipano un'interfaccia di funzioni.

Possono anche essere usati più o meno nello stesso modo:invece di passare un'intera classe che contiene il metodo di cui hai bisogno puoi passare solo un delegato.Ciò consente di risparmiare un sacco di codice e crea codice molto più leggibile.

Inoltre, con l'avvento delle espressioni lambda, ora possono essere definite facilmente anche al volo, il che è un enorme vantaggio.Sebbene sia POSSIBILE creare classi al volo in C#, è davvero una grande seccatura.

Confrontare i due è un concetto interessante.In precedenza non avevo considerato quanto le idee fossero simili dal punto di vista del caso d'uso e della strutturazione del codice.

Un delegato ha molto in comune con un riferimento all'interfaccia che ha un unico metodo dal punto di vista del chiamante.

Nel primo esempio, Baz e Bar sono classi che possono essere ereditate e istanziate.Nel secondo esempio, Baz e Bar sono metodi.

Non è possibile applicare riferimenti all'interfaccia a qualsiasi classe che corrisponda al contratto dell'interfaccia.La classe deve dichiarare esplicitamente che supporta l'interfaccia.È possibile applicare un riferimento delegato a qualsiasi metodo che corrisponda alla firma.

Non è possibile includere metodi statici nel contratto di un'interfaccia.(Sebbene sia possibile integrare metodi statici con metodi di estensione).È possibile fare riferimento ai metodi statici con un riferimento al delegato.

No, i delegati servono per i puntatori ai metodi.Quindi puoi assicurarti che la firma del metodo associato al delegato sia corretta.

Inoltre, non è necessario conoscere la struttura della classe.In questo modo, puoi utilizzare un metodo che hai scritto per passarlo a un metodo in un'altra classe e definire la funzionalità che desideri che si verifichi.

Dai un'occhiata a Classe List<> con il metodo Find.Ora puoi definire cosa determina se qualcosa corrisponde o meno, senza richiedere che gli elementi contenuti nella classe implementino IListFindable o qualcosa di simile.

Puoi passare i delegati come parametri nelle funzioni (Ok tecnicamente i delegati diventano oggetti quando compilati, ma non è questo il punto qui).Potresti passare un oggetto come parametro (ovviamente), ma poi stai legando quel tipo di oggetto alla funzione come parametro.Con i delegati puoi passare qualsiasi funzione da eseguire nel codice che ha la stessa firma indipendentemente dalla sua provenienza.

Si può pensare ai delegati come a un'interfaccia per un metodo che definisce quali argomenti e tipo di ritorno deve avere un metodo per adattarsi al delegato

Sì, un delegato può essere considerato come un'interfaccia con un metodo.

Un delegato è un puntatore al metodo tipizzato.Ciò ti offre maggiore flessibilità rispetto alle interfacce perché puoi sfruttare la covarianza e la controvarianza e puoi modificare lo stato dell'oggetto (dovresti passare il puntatore this con funtori basati sull'interfaccia).

Inoltre, i delegati hanno un sacco di zucchero sintattico che ti consente di fare cose come combinarli insieme facilmente.

Interfacce e delegati sono due cose completamente diverse, anche se capisco la tentazione di descrivere i delegati in termini simili a quelli di un'interfaccia per facilitare la comprensione... tuttavia, non conoscere la verità può portare a confusione in futuro.

I delegati sono stati ispirati (in parte) dal fatto che l'arte nera dei puntatori del metodo C++ era inadeguata per determinati scopi.Un classico esempio è l'implementazione di un meccanismo di passaggio di messaggi o di gestione di eventi.I delegati ti consentono di definire una firma del metodo senza alcuna conoscenza dei tipi o delle interfacce di una classe: potrei definire un delegato "void eventHandler(Event* e)" e invocarlo su qualsiasi classe che lo ha implementato.

Per comprendere meglio questo classico problema e perché i delegati sono desiderabili leggi questo poi Questo.

In almeno una proposta per aggiungere chiusure (ad es.delegati anonimi) a Java, sono equivalenti alle interfacce con un metodo a membro singolo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top