Frage

Kann jemand bitte brechen, was ein Delegierter in eine einfache, kurze und knappe Erklärung, dass dies schließt den Zweck und die allgemeinen Vorteile? Ich habe versucht, meinen Kopf um diesen zu wickeln und es ist einfach nicht versinkt in.

War es hilfreich?

Lösung

In den einfachsten möglichen Bedingungen, es ist im Wesentlichen ein Zeiger auf ein Verfahren.

Sie können eine Variable, die einen Delegattyp hält (wie Sie eine int-Variable haben würde, die einen int-Typ aufnehmen kann). Sie können die Methode ausführen, dass die Delegierten Punkte, indem Sie einfach Ihre Variable wie eine Funktion aufrufen.

Auf diese Weise können Sie nur variable Funktionen haben wie Sie variable Daten haben könnten. Ihre Aufgabe kann Delegierten von anderen Objekten übernehmen und nennen sie, ohne alle möglichen Funktionen selbst definieren zu müssen.

Das ist sehr praktisch, wenn Sie ein Objekt wollen die Dinge zu tun, basierend auf Benutzer festgelegten Kriterien. Zum Beispiel Filtern einer Liste auf der Basis eines benutzerdefinierten true / false-Expression. Sie können die Benutzer lassen die Delegatfunktion angeben als Filter zu verwenden, um gegen jedes Listenelement zu bewerten.

Andere Tipps

Ich habe eine Funktion:

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

Diese Funktion saugt. Was passiert, wenn ich will 3 * 3?

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

Zu viel Typisierung. Ich bin faul!

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

Meine SquareOf Funktion kümmert sich nicht darum, was n ist. Es wird richtig funktioniert für jeden n in geben. Es nicht genau weiß, was Zahl n ist, aber es nicht weiß, dass n eine ganze Zahl ist. Sie können nicht "Haha not an integer" in SquareOf passieren.

Hier ist eine andere Funktion:

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

Im Gegensatz zu seinem Namen, hat DoSomethingRad nicht wirklich etwas rad tun. Allerdings ist es die SquareOf (4) schreiben, das ist 16. Können wir es weniger langweilig sein ändern?

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

DoSomethingRad ist eindeutig immer noch ziemlich fehl. Aber zumindest können wir jetzt in einer Reihe auf Platz passieren, so wird es nicht 16 schreibt jedes Mal. (Es wird 1 schreiben, oder 4 oder 9 oder 16, oder ... zzzz noch irgendwie langweilig).

Es wäre schön, wenn es einen Weg zu ändern, was zu der Zahl geschieht übergeben Vielleicht liegt es wollen wir nicht zu quadrieren. vielleicht wollen wir es Würfel, oder subtrahieren sie von 69 (Anzahl zufällig aus meinem Kopf ausgewählt).

Bei einer weiteren Inspektion, es scheint, als ob das nur ein Teil der SquareOf dass DoSomethingRad Sorgen über ist, dass wir es für eine ganze Zahl (numberToSquare) geben kann und dass es gibt uns eine long (weil wir den Rückgabewert in y setzen und y ist a long).

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

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

Sehen Sie, wie ähnlich DoSomethingLeet zu DoSomethingRad ist? Wenn es nur eine Möglichkeit, in weitergeben Verhalten (DoX()) statt nur Daten (int n) ...

So, jetzt, wenn wir ein Quadrat einer Zahl schreiben wollen, können wir DoSomethingRad und wenn wir die dritte Potenz einer Zahl schreiben wollen, können wir DoSomethingLeet. Wenn wir also von 69 die Zahl subtrahiert schreiben wollen, müssen wir eine andere Methode, DoSomethingCool machen? Nein, denn das ist auch verdammt viel Tipparbeit nimmt (und was noch wichtiger ist, es behindert unsere Fähigkeit, alter interessantes Verhalten durch nur ein Aspekt unseres Programms zu ändern).

So kommen wir zu:

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

Wir können diese Methode aufrufen, indem Sie dieses Schreiben:

Radlicious(77, SquareOf);

Func<int, long> ist eine besondere Art von Delegierten. Es speichert Verhalten, das ganze Zahlen und spuckt longs akzeptiert. Wir sind nicht sicher, was die Methode verweist er auf geht mit jeder gegebenen zu tun integer wir gehen; alles, was wir wissen, ist, dass, was auch immer geschieht, werden wir einen long zurück.

Wir müssen keine Parameter zu SquareOf geben, weil Func<int, long> beschreibt Verhalten , keine Daten. Der Aufruf Radlicious(77, SquareOf) gibt nur Radlicious das allgemeine Verhalten von SquareOf ( „Ich nehme eine Nummer und gibt dessen Platz“), nicht das, was SquareOf tun einem spezifische integer.

Nun, wenn Sie verstanden haben, was ich sage, dann haben Sie mir schon ein upped, denn ich selbst nicht wirklich das Zeug bekommen.

* END ANTWORT, WANDERING IDIOTIE BEGIN *

Ich meine, wie es scheint, ints als nur wirklich langweilig Verhalten wahrgenommen werden könnte:

static int Nine()
{
    return 9;
}

sagte, dass die Linie zwischen dem, was Daten und Verhalten scheint zu verschwimmen, mit dem, was normalerweise als Daten wahrgenommen wird, ist einfach langweilig-ass Verhalten.

Natürlich könnte man sich vorstellen, super „interessant“ Verhalten, die alle Arten von abstrakten Parameter nimmt, erfordert aber eine Menge Informationen, um es zu nennen. Was passiert, wenn es uns erforderlich, um den Quellcode zu liefern, dass es für uns kompiliert und ausgeführt würde?

Nun, dann unsere Abstraktion scheint uns den Weg zurück alle auf Platz eins bekommen zu haben. Wir haben das Verhalten so abstrakt sie den gesamten Quellcode unseres Programms erfordert, um zu bestimmen, was es tun wird. Dies ist völlig unbestimmt behavior: die Funktion kann tun alles , aber es hat mit zur Verfügung gestellt werden alles , um zu bestimmen, was sie tut. Auf der anderen Seite, ganz bestimmtes Verhalten, wie Nine(), benötigt keine zusätzliche Informationen, kann aber nichts anderes als Rückkehr 9 tun.

So what? Ich weiß es nicht.

A delegieren ist ein Zeiger auf ein Verfahren. Anschließend können Sie Ihre Stellvertretung als Parameter anderer Methoden.

hier ist ein Link zu einem einfachen Tutorial.

Die Frage, die ich hatte, war ‚Also, warum sollte ich das tun?‘ Sie werden nicht wirklich ‚es bekommen‘, bis Sie ein Programmierproblem mit ihnen zu lösen.

Es ist interessant, dass niemand einen der wichtigsten Vorteile der Delegation erwähnt hat - es ist vorzuziehen Unter Klassierung, wenn du das Erbe erkennen ist kein Wundermittel und schafft in der Regel mehr Probleme als sie löst. Es ist die Grundlage vieler Entwurfsmuster, vor allem der Strategie Muster.

A Delegatinstanz ist ein Verweis auf ein Verfahren. Der Grund warum sie nützlich sind, ist, dass Sie einen Delegaten erstellen können, die auf ein bestimmtes Verfahren auf einer bestimmten Instanz eines Typs gebunden ist. Die Delegate-Instanz ermöglicht es Ihnen, diese Methode auf diesem speziellen Fall zu berufen, selbst wenn das Objekt, auf dem Sie die Methode aufrufen, wird Ihre lexikalischen Gültigkeitsbereich verlassen hat.

Die häufigste Verwendung für die Delegierten Fälle wie dieser ist das Konzept der Rückrufe .

Es verweist einfach eine Methode. Sie kommen in großem Einsatz mit mit Quer Threading arbeiten.

Hier ist ein Beispiel direkt aus meinem Code.

 //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

Wenn Sie einen Delegaten verwenden didnt Sie nicht in der Lage sein, die Lobby.AdRotator Funktion crossthread und rufen.

Wie schon andere gesagt haben, ist ein Delegat ein Verweis auf eine Funktion. Eine der sinnvollen Nutzungsmöglichkeiten (IMO) ist Ereignisse. Wenn Sie ein Ereignis registrieren Sie eine Funktion für das Ereignis invoke registrieren, und die Delegierten für diese Aufgabe perfekt sind.

In den grundlegendsten Bedingungen ist ein Delegierter nur eine Variable, die enthält (eine Referenz auf) eine Funktion. Die Delegierten sind nützlich, weil sie ermöglicht es Ihnen, eine Funktion zu übergeben um als Variable ohne Bedenken für „wo“ die Funktion von tatsächlich kam.

Es ist wichtig zu beachten, natürlich, dass die Funktion nicht kopiert wird, wenn es in einer Variablen gebündelt werden; es ist nur durch Bezugnahme gebunden zu sein. Zum Beispiel:

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();

In den meisten einfachen Worten ausgedrückt, die Verantwortung, ein Verfahren auszuführen, auf ein anderes Objekt übertragen. Sagen der Präsident von einigen Nation stirbt und der Präsident der USA soll für die Beerdigung mit Beileid Nachricht anwesend sein. Wenn der Präsident der USA nicht in der Lage ist zu gehen, wird delegiert er diese Verantwortung an jemanden entweder der Vizepräsidenten oder der Sekretär des Staates.

Das Gleiche gilt im Code. Ein Beauftragter ist ein Typ, es ist eine Aufgabe, die der Ausführung des Verfahrens geeignet ist.

zB.

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);
  }

}

Die GetPersonName Methode wird mit dem Delegatobjekt personNameDelegate genannt. Alternativ können wir die PrintNameUsingDelegate Verfahren haben einen Delegaten als Parameter zu nehmen.

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

Der Vorteil ist, wenn jemand den Namen als lastname_firstname ausdrucken möchten, er / sie hat nur diese Methode in personNameDelegate wickeln und an diese Funktion übergeben. Keine weitere Codeänderung erforderlich ist.

Die Delegierten sind besonders wichtig in

  1. Veranstaltungen
  2. Asynchronous ruft
  3. LINQ (als Lambda-Ausdrücke)

Wenn Sie eine Aufgabe, jemanden delegieren würden, würde die Delegierten die Person, die die Arbeit erhält.

In der Programmierung ist es ein Verweis auf den Code-Block, der wirklich weiß, wie etwas zu tun. Oft ist dies ein Zeiger auf die Funktion oder Methode, die einen Gegenstand behandelt.

In den absoluten einfachsten Bedingungen kann ich kommen mit dieser ist: Ein Delegierter wird die Last der Arbeit in die Hände einer Klasse zwingen, dass ziemlich viel weiß, was zu tun ist. Betrachten Sie es als ein Kind, das nicht erwachsen werden will wie sein großer Bruder vollständig zu sein, aber muss noch seine Führung und Aufträge. Statt alle Methoden von seinem Bruder zu erben (dh Subklassifizieren), er macht nur seinen Bruder tun die Arbeit oder Der kleine Bruder etwas tut, das Handeln erfordert von den großen Bruder genommen werden. Wenn Sie in den Zeilen der Protokolle fallen, was der große Bruder definiert absolut erforderlich ist, oder er könnte Ihnen Flexibilität, zu entscheiden, was Sie ihm zu tun in bestimmten Ereignissen (dh informelle und formelle Protokolle in Objective-C wie beschrieben) machen wollen.

Der absolute Vorteil dieses Konzeptes besteht darin, dass Sie nicht über eine Unterklasse erstellen müssen. Wenn Sie etwas in Linie fallen wollen, Befehle befolgen, wenn ein Ereignis eintritt, kann der Delegat eine entwickelte Klasse sie an der Hand halten und Befehle geben, wenn nötig.

scroll top