Domanda

Qualcuno può abbattere ciò che un delegato è in una spiegazione semplice, breve e concisa che comprende sia lo scopo e vantaggi generali? Ho cercato di avvolgere la mia testa intorno a questo e non è solo affondare in.

È stato utile?

Soluzione

In termini più semplici possibili, è essenzialmente un puntatore ad un metodo.

Si può avere una variabile che contiene un tipo delegato (proprio come si avrebbe una variabile int che può contenere un tipo int). È possibile eseguire il metodo che i punti delegato a semplicemente chiamando la variabile come una funzione.

Questo permette di avere funzioni di variabile, proprio come si potrebbe avere dati variabili. Il vostro oggetto può accettare delegati di altri oggetti e li chiamano, senza dover definire tutte le possibili funzioni si.

Questo è molto utile quando si desidera un oggetto per fare le cose sulla base di criteri specificati dall'utente. Ad esempio, filtrare un elenco basato su un vero falso un'espressione definita dall'utente /. È possibile consentire all'utente di specificare la funzione di delegato da usare come filtro per valutare ogni elemento della lista contro.

Altri suggerimenti

Ho una funzione:

public long GiveMeTwoTimesTwo()
{
    return 2 * 2;
}

Questa funzione fa schifo. Che cosa devo fare 3 * 3?

public long GiveMeThreeTimesThree()
{
    return 3 * 3;
}

Troppo digitazione. Sono pigro!

public long SquareOf(int n)
{
    return n * n;
}

La mia funzione SquareOf non importa quello che è n. Essa funzionerà correttamente per qualsiasi n passata. Non sa esattamente che cosa il numero n è, ma ha sanno che n è un numero intero. Non è possibile passare in "Haha not an integer" SquareOf.

Ecco un'altra funzione:

public void DoSomethingRad()
{
    int x = 4;
    long y = SquareOf(x);
    Console.WriteLine(y);
}

Contrariamente al suo nome, DoSomethingRad in realtà non fa nulla rad. Tuttavia, lo fa scrivere l'SquareOf (4) che è 16. Possiamo cambiare per essere meno noioso?

public void DoSomethingRad(int numberToSquare)
{
    long y = SquareOf(numberToSquare);
    Console.WriteLine(y);
}

DoSomethingRad è chiaramente ancora piuttosto fallire. Ma almeno ora possiamo passare in un certo numero di quadrati, in modo da non scrivere 16 ogni volta. (Si scriverà 1, o 4, o 9, o 16, o ... zzzz ancora un pò noioso).

Sarebbe bello se ci fosse un modo per cambiare ciò che accade al numero passata Forse non vogliamo far quadrare esso.; forse vogliamo cubo, o sottrarre dal 69 (numero scelto a caso dalla mia testa).

In un'ulteriore ispezione, sembra che l'unica parte del SquareOf che DoSomethingRad si preoccupa sta che siamo in grado di dare un numero intero (numberToSquare) e che ci dà un long (perché abbiamo messo il suo valore di ritorno in y e y è un long).

public long CubeOf(int n)
{
    return n * n * n;
}

public void DoSomethingLeet(int numberToSquare)
{
    long y = CubeOf(numberToSquare);
    Console.WriteLine(y);
}

Si veda quanto simile DoSomethingLeet è quello di DoSomethingRad? Se solo ci fosse un modo per passare in comportamento (DoX()) invece di Dati (int n) ...

Ora, se vogliamo scrivere un quadrato di un numero, possiamo DoSomethingRad e se vogliamo scrivere il cubo di un numero, possiamo DoSomethingLeet. Quindi, se vogliamo scrivere il numero sottratto dal 69, dobbiamo fare un altro metodo, DoSomethingCool? No, perché questo richiede troppo dannatamente tanto digitazione (e, soprattutto, ostacola la nostra capacità di alterare il comportamento interessante cambiando solo un aspetto del nostro programma).

Si arriva così al:

public long Radlicious(int doSomethingToMe, Func<int, long> doSomething)
{
    long y = doSomething(doSomethingToMe);
    Console.WriteLine(y);
}

Possiamo chiamare questo metodo per scrivere questo:

Radlicious(77, SquareOf);

Func<int, long> è un tipo speciale di delegato. Memorizza comportamento che accetta numeri interi e sputa fuori longs. Non siamo sicuri di ciò che il metodo a cui punta sta andando a che fare con un dato intero si passa; tutto quello che sappiamo è che, qualunque cosa accada, stiamo per ottenere un long indietro.

Non abbiamo dare alcun parametro per SquareOf perché Func<int, long> descrive comportamento , non i dati. Chiamando Radlicious(77, SquareOf) dà solo Radlicious il comportamento generale di SquareOf ( "Prendo un numero e restituisce la sua piazza"), non quello SquareOf farà qualsiasi specifica numero intero.

Ora, se hai capito quello che sto dicendo, allora avete già me uno-ha alzato, perché io stesso non capisco proprio questa roba.

* END RISPOSTA, BEGIN ERRANTE IDIOZIA *

Voglio dire, sembra che ints potrebbero essere percepiti come comportamenti solo molto noioso:

static int Nine()
{
    return 9;
}

Detto questo, la linea di demarcazione tra ciò che è di dati e il comportamento sembra assottigliare, con ciò che viene normalmente percepito come dati è semplicemente un comportamento noioso-ass.

Naturalmente, si potrebbe immaginare eccellente comportamento "interessante", che prende tutti i tipi di parametri astratti, ma richiede un sacco di informazioni per essere in grado di chiamarla. Che cosa succede se ci si deve fornire il codice sorgente che sarebbe compilare ed eseguire per noi?

Bene, allora la nostra astrazione sembra averci preso tutta la strada fino al punto di partenza. Abbiamo comportamento in modo astratto che richiede l'intero codice sorgente del nostro programma per determinare ciò che sta per fare. Questo è behavio completamente indeterminataR: la funzione può fare niente , ma deve essere dotato di tutto per determinare ciò che fa. D'altra parte, un comportamento pienamente determinato, come ad esempio Nine(), non ha bisogno di ulteriori informazioni, ma non può fare altro che 9 ritorno.

E allora? Non lo so.

Un delegato è un puntatore a un metodo. È quindi possibile utilizzare il delegato come parametro di altri metodi.

qui è un link ad un semplice tutorial.

La domanda che avevo era 'Allora, perché dovrei farlo?' Non sarà davvero 'ottenerlo' fino a risolvere un problema di programmazione con loro.

E 'interessante il fatto che nessuno ha menzionato uno dei vantaggi chiave di delegazione - è preferibile sub-classing quando ti rendi conto che l'ereditarietà non è una bacchetta magica e di solito crea più problemi di quanti ne risolva. E 'la base di molti modelli di progettazione, in particolare il strategia modello.

Un esempio delegato è un riferimento a un metodo. Il motivo per cui sono utili è che è possibile creare un delegato che è legato ad un particolare metodo su una particolare istanza di un tipo. L'istanza delegato consente di richiamare il metodo in quel caso particolare, anche se l'oggetto su cui verrà richiamare il metodo ha lasciato l'ambito lessicale.

L'uso più comune per le istanze dei delegati come questo è quello di sostenere il concetto di callback a livello di lingua.

Si fa riferimento semplicemente un metodo. Essi sono disponibili in grande uso con il lavoro con filettatura croce.

Ecco un esempio a destra, fuori del mio codice.

 //Start our advertisiment thread
    rotator = new Thread(initRotate);
    rotator.Priority = ThreadPriority.Lowest;
    rotator.Start();

    #region Ad Rotation
    private delegate void ad();
    private void initRotate()
    {
        ad ad = new ad(adHelper);
        while (true)
        {
            this.Invoke(ad);
            Thread.Sleep(30000);
        }

    }

    private void adHelper()
    {
        List<string> tmp = Lobby.AdRotator.RotateAd();
        picBanner.ImageLocation = @tmp[0].ToString();
        picBanner.Tag = tmp[1].ToString();            
    }
    #endregion

Se provata un delegato che non sarebbe in grado di torcere e chiamare la funzione Lobby.AdRotator.

Come altri hanno detto, un delegato è un riferimento a una funzione. Uno degli usi più vantaggioso (IMO) è eventi. Al momento della registrazione di un evento si registra una funzione per l'evento di invocare, e delegati sono perfetti per questo compito.

In termini più elementari, un delegato è solo una variabile che contiene (un riferimento a) una funzione. I delegati sono utili perché consentono di passare una funzione intorno come una variabile senza alcuna preoccupazione per "dove" la funzione in realtà è venuto da.

E 'importante notare, naturalmente, che la funzione non viene copiato quando è in fase di infagottato in una variabile; è solo di essere vincolato da riferimento. Ad esempio:

class Foo
{
    public string Bar
    {
        get;
        set;
    }

    public void Baz()
    {
        Console.WriteLine(Bar);
    }
}

Foo foo = new Foo();
Action someDelegate = foo.Baz;

// Produces "Hello, world".
foo.Bar = "Hello, world";
someDelegate();

Nella maggior parte dei termini più semplici, la responsabilità di eseguire un metodo è delegata a un altro oggetto. Dicono che il presidente di qualche nazione muore e il presidente degli Stati Uniti dovrebbe essere presente per il funerale con il messaggio condoglianze. Se il presidente degli Stati Uniti non è in grado di andare, egli delegare questa responsabilità a qualcuno sia il vice-presidente o il segretario di Stato.

Lo stesso vale nel codice. Un delegato è un tipo, è un oggetto che è in grado di eseguire il metodo.

ad es.

Class Person
{
   public string GetPersonName(Person person)
   {
     return person.FirstName + person.LastName;
   }

   //Calling the method without the use of delegate
   public void PrintName()
   {
      Console.WriteLine(GetPersonName(this));
   }

   //using delegate
   //Declare delegate which matches the methods signature
   public delegate string personNameDelegate(Person person);

  public void PrintNameUsingDelegate()
  {
      //instantiate
      personNameDelegate = new personNameDelegate(GetPersonName);

      //invoke
      personNameDelegate(this);
  }

}

Il metodo GetPersonName viene chiamato con il personNameDelegate oggetto delegato. In alternativa possiamo avere il metodo PrintNameUsingDelegate di prendere un delegato come parametro.

public void PrintNameUsingDelegate(personNameDelegate pnd, Person person)
{
   pnd(person);
}

Il vantaggio è che se qualcuno desidera stampare il nome come lastname_firstname, s / egli deve solo avvolgere quel metodo in personNameDelegate e passare a questa funzione. Non è richiesta alcuna ulteriore modifica del codice.

I delegati sono specificamente importante

  1. Eventi
  2. asincrono chiama
  3. LINQ (come espressioni lambda)

Se si dovesse andare a delegare un compito a qualcuno, il delegato sarebbe la persona che riceve il lavoro.

Nella programmazione, si tratta di un riferimento al blocco di codice che effettivamente sa come fare qualcosa. Spesso questo è un puntatore a funzione o del metodo che si occuperà qualche elemento.

In termini assoluti la maggior parte delle più semplici posso venire in mente è questa: Un delegato costringerà gli oneri del lavoro nelle mani di una classe che sa più o meno cosa fare. Pensate a come un bambino che non vuole crescere fino ad essere come il suo grande fratello completamente, ma ha ancora bisogno la sua guida e gli ordini. Invece di ereditare tutti i metodi da suo fratello (cioè sottoclassi), fa solo il suo fratello fare il lavoro o il fratellino fa qualcosa che richiede azioni da intraprendere da parte del fratello maggiore. Quando cadi nelle linee dei protocolli, il fratello maggiore definisce ciò che è assolutamente necessario, o lui potrebbe dare flessibilità di scegliere ciò che si desidera fargli fare in determinati eventi (ad esempio protocolli formali e informali, come indicato in Objective-C).

Il beneficio assoluto di questo concetto è che non c'è bisogno di creare una sottoclasse. Se volete qualcosa di cadere in linea, seguire gli ordini, quando si verifica un evento, il delegato consente una classe sviluppata da tenere è la mano e dare ordini, se necessario.

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