438 Stimmen

Wann und warum sollte man Delegierte einsetzen?

Ich bin relativ neu in C#, und ich frage mich wann man Delegierte richtig einsetzt . Sie werden häufig bei der Erklärung von Ereignissen verwendet, aber wann sollte ich sie in meinem eigenen Code verwenden und Warum sind sie nützlich? warum nicht etwas anderes verwenden?

Ich frage mich auch wenn ich Delegierte einsetzen muss und keine andere Möglichkeit habe .

Vielen Dank für die Hilfe!

EDIT: Ich glaube, ich habe eine notwendiger Einsatz von Delegierten aquí

379voto

dhaval8087 Punkte 1

Ein Delegat ist ein Verweis auf eine Methode. Während Objekte leicht als Parameter in Methoden, Konstruktoren oder was auch immer gesendet werden können, sind Methoden ein bisschen schwieriger. Aber hin und wieder haben Sie vielleicht das Bedürfnis, eine Methode als Parameter an eine andere Methode zu senden, und dann brauchen Sie Delegaten.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DelegateApp {

  /// <summary>
  /// A class to define a person
  /// </summary>
  public class Person {
    public string Name { get; set; }
    public int Age { get; set; }
  }

  class Program {
    //Our delegate
    public delegate bool FilterDelegate(Person p);

    static void Main(string[] args) {

      //Create 4 Person objects
      Person p1 = new Person() { Name = "John", Age = 41 };
      Person p2 = new Person() { Name = "Jane", Age = 69 };
      Person p3 = new Person() { Name = "Jake", Age = 12 };
      Person p4 = new Person() { Name = "Jessie", Age = 25 };

      //Create a list of Person objects and fill it
      List<Person> people = new List<Person>() { p1, p2, p3, p4 };

      //Invoke DisplayPeople using appropriate delegate
      DisplayPeople("Children:", people, IsChild);
      DisplayPeople("Adults:", people, IsAdult);
      DisplayPeople("Seniors:", people, IsSenior);

      Console.Read();
    }

    /// <summary>
    /// A method to filter out the people you need
    /// </summary>
    /// <param name="people">A list of people</param>
    /// <param name="filter">A filter</param>
    /// <returns>A filtered list</returns>
    static void DisplayPeople(string title, List<Person> people, FilterDelegate filter) {
      Console.WriteLine(title);

      foreach (Person p in people) {
        if (filter(p)) {
          Console.WriteLine("{0}, {1} years old", p.Name, p.Age);
        }
      }

      Console.Write("\n\n");
    }

    //==========FILTERS===================
    static bool IsChild(Person p) {
      return p.Age < 18;
    }

    static bool IsAdult(Person p) {
      return p.Age >= 18;
    }

    static bool IsSenior(Person p) {
      return p.Age >= 65;
    }
  }
}

Ausgabe:

Children:
Jake, 12 years old

Adults:
John, 41 years old
Jane, 69 years old
Jessie, 25 years old

Seniors:
Jane, 69 years old

347voto

Benoît Vidis Punkte 3826

Ich stimme mit allem überein, was bereits gesagt wurde, und versuche nur, es mit anderen Worten auszudrücken.

Ein Delegat kann als Platzhalter für eine/mehrere Methode(n) betrachtet werden.

Indem Sie einen Delegaten definieren, sagen Sie dem Benutzer Ihrer Klasse, " Sie können dem Delegaten eine beliebige Methode zuweisen, die mit dieser Signatur übereinstimmt, und sie wird jedes Mal aufgerufen, wenn mein Delegat aufgerufen wird ".

Typische Anwendung sind natürlich Veranstaltungen. Alle OnEventX delegieren zu den Methoden, die der Benutzer definiert.

Delegierte sind nützlich, um den Benutzer Ihrer Objekte einige Möglichkeiten, ihr Verhalten anzupassen. Die meiste Zeit können Sie andere Wege nutzen, um den gleichen Zweck zu erreichen, und ich glaube nicht, dass Sie jemals sein können gezwungen um Delegierte zu erstellen. Das ist in manchen Situationen einfach der einfachste Weg, um die Sache zu erledigen.

159voto

Alex Budovski Punkte 17158

Angenommen, Sie wollen eine Prozedur zur Integration einer reellen Funktion schreiben f ( x ) über ein Intervall [a, b]. Nehmen wir an, wir wollen dazu die 3-Punkt-Gauß-Methode verwenden (natürlich ist jede andere Methode geeignet).

Idealerweise wollen wir eine Funktion, die wie folgt aussieht:

// 'f' is the integrand we want to integrate over [a, b] with 'n' subintervals.
static double Gauss3(Integrand f, double a, double b, int n) {
  double res = 0;

  // compute result
  // ...

  return res;
}

Wir können also eine beliebige Integrand , f und ihr definitives Integral über das geschlossene Intervall erhalten.

Nur welche Art sollte Integrand sein?

Ohne Delegierte

Nun, ohne Delegierte bräuchten wir eine Art von Schnittstelle mit einer einzigen Methode, sagen wir eval wie folgt erklärt:

// Interface describing real-valued functions of one variable.
interface Integrand {
  double eval(double x);
}

Dann müssten wir eine ganze Reihe von Klassen erstellen, die diese Schnittstelle implementieren, wie folgt:

// Some function
class MyFunc1 : Integrand {
  public double eval(double x) {
    return /* some_result */ ;
  }
}

// Some other function
class MyFunc2 : Integrand {
  public double eval(double x) {
    return /* some_result */ ;
  }
}

// etc

Um sie dann in unserer Gauss3-Methode zu verwenden, müssen wir sie wie folgt aufrufen:

double res1 = Gauss3(new MyFunc1(), -1, 1, 16);
double res2 = Gauss3(new MyFunc2(), 0, Math.PI, 16);

Und Gauss3 muss wie folgt aussehen:

static double Gauss3(Integrand f, double a, double b, int n) {
  // Use the integrand passed in:
  f.eval(x);
}

Wir müssen also all das tun, nur um unsere willkürlichen Funktionen in Guass3 .

Mit Delegierten

public delegate double Integrand(double x);

Jetzt können wir einige statische (oder nicht) Funktionen definieren, die diesem Prototyp entsprechen:

class Program {
   public delegate double Integrand(double x);   
   // Define implementations to above delegate 
   // with similar input and output types
   static double MyFunc1(double x) { /* ... */ }
   static double MyFunc2(double x) { /* ... */ }
   // ... etc ...

   public static double Gauss3(Integrand f, ...) { 
      // Now just call the function naturally, no f.eval() stuff.
      double a = f(x); 
      // ...
   }

   // Let's use it
   static void Main() {
     // Just pass the function in naturally (well, its reference).
     double res = Gauss3(MyFunc1, a, b, n);
     double res = Gauss3(MyFunc2, a, b, n);    
   }
}

Keine Schnittstellen, kein klobiges .eval-Zeug, keine Objektinstanziierung, nur eine einfache Verwendung von Funktionszeigern für eine einfache Aufgabe.

Natürlich sind Delegierte mehr als nur Funktionszeiger unter der Haube, aber das ist ein anderes Thema (Funktionsverkettung und Ereignisse).

34voto

Jan Jongboom Punkte 25470

Delegates sind äußerst nützlich, wenn Sie einen Codeblock deklarieren wollen, den Sie weitergeben möchten. Zum Beispiel bei der Verwendung eines generischen Wiederholungsmechanismus.

Pseudo:

function Retry(Delegate func, int numberOfTimes)
    try
    {
       func.Invoke();
    }
    catch { if(numberOfTimes blabla) func.Invoke(); etc. etc. }

Oder wenn Sie eine späte Auswertung von Codeblöcken vornehmen wollen, wie z.B. eine Funktion, bei der Sie einige Transform Aktion, und wollen eine BeforeTransform und ein AfterTransform Aktion, die Sie innerhalb Ihrer Transform-Funktion auswerten können, ohne dass Sie wissen müssen, ob die BeginTransform gefüllt ist, oder was es umzuwandeln hat.

Und natürlich bei der Erstellung von Ereignishandlern. Sie wollen den Code nicht jetzt auswerten, sondern erst bei Bedarf, also registrieren Sie einen Delegaten, der aufgerufen werden kann, wenn das Ereignis eintritt.

30voto

Lukas Šalkauskas Punkte 13681

Delegierte Übersicht

Delegierte haben die folgenden Eigenschaften:

  • Delegate sind ähnlich wie C++-Funktionszeiger, aber typsicher.
  • Mit Delegaten können Methoden als Parameter übergeben werden.
  • Delegate können verwendet werden, um Rückrufmethoden zu definieren.
  • Delegate können miteinander verkettet werden; so können beispielsweise mehrere Methoden bei einem einzigen Ereignis aufgerufen werden.
  • Die Methoden müssen nicht genau mit der Signatur des Delegaten übereinstimmen. Weitere Informationen finden Sie unter Kovarianz und Contravarianz.
  • C# Version 2.0 führt das Konzept der Anonymen Methoden ein, die es erlauben, Codeblöcke als Parameter anstelle einer separat definierten Methode zu übergeben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X