Grundlegendes zu Ereignissen und Ereignishandlern in C #

329

Ich verstehe den Zweck von Ereignissen, insbesondere im Zusammenhang mit der Erstellung von Benutzeroberflächen. Ich denke, dies ist der Prototyp für die Erstellung eines Ereignisses:

public void EventName(object sender, EventArgs e);

Was machen Event-Handler, warum werden sie benötigt und wie erstelle ich einen?

Levi Campbell
quelle
9
Wie von @Andy angegeben, beschreibt das Code-Snippet hier die für das Ereignis registrierte Methode, nicht das Ereignis selbst.
Dthrasher

Antworten:

659

Um Ereignishandler zu verstehen, müssen Sie die Delegaten verstehen . In C # können Sie sich einen Delegaten als Zeiger (oder Referenz) auf eine Methode vorstellen. Dies ist nützlich, da der Zeiger als Wert übergeben werden kann.

Das zentrale Konzept eines Delegierten ist seine Unterschrift oder Form. Das ist (1) der Rückgabetyp und (2) die Eingabeargumente. Wenn wir beispielsweise einen Delegaten erstellen void MyDelegate(object sender, EventArgs e), kann dieser nur auf Methoden verweisen, die zurückgeben void, und ein objectund nehmen EventArgs. Ein bisschen wie ein quadratisches Loch und ein quadratischer Stift. Wir sagen also, dass diese Methoden dieselbe Signatur oder Form haben wie der Delegat.

Wenn wir also wissen, wie ein Verweis auf eine Methode erstellt wird, lassen Sie uns über den Zweck von Ereignissen nachdenken: Wir möchten, dass Code ausgeführt wird, wenn an einer anderen Stelle im System etwas passiert - oder "das Ereignis behandeln". Dazu erstellen wir spezielle Methoden für den Code, den wir ausführen möchten. Der Klebstoff zwischen dem Ereignis und den auszuführenden Methoden sind die Delegierten. Das Ereignis muss intern eine "Liste" von Zeigern auf die Methoden speichern, die beim Auslösen des Ereignisses aufgerufen werden sollen. * Um eine Methode aufrufen zu können, müssen wir natürlich wissen, welche Argumente an sie übergeben werden müssen! Wir verwenden den Delegaten als "Vertrag" zwischen der Veranstaltung und allen spezifischen Methoden, die aufgerufen werden.

Die Standardeinstellung EventHandler(und viele davon mögen sie) repräsentiert also eine bestimmte Form der Methode (wiederum void / object-EventArgs). Wenn Sie ein Ereignis deklarieren, geben Sie an, welche Methodenform (EventHandler) dieses Ereignis aufruft, indem Sie einen Delegaten angeben:

//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyEventHandler(string foo);

//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyEventHandler SomethingHappened;

//Here is some code I want to be executed
//when SomethingHappened fires.
void HandleSomethingHappened(string foo)
{
    //Do some stuff
}

//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);

//To raise the event within a method.
SomethingHappened("bar");

(* Dies ist der Schlüssel zu Ereignissen in .NET und entfernt die "Magie" - ein Ereignis ist im Grunde genommen nur eine Liste von Methoden mit derselben "Form". Die Liste wird dort gespeichert, wo das Ereignis lebt. Wann Das Ereignis wird "ausgelöst", es ist wirklich nur "diese Liste von Methoden durchgehen und jede aufrufen, wobei diese Werte als Parameter verwendet werden". Das Zuweisen eines Ereignishandlers ist nur eine schönere und einfachere Möglichkeit, Ihre Methode zu dieser Liste von Methoden hinzuzufügen heißen).

Rex M.
quelle
24
Und jetzt kann jemand erklären, warum das Ereignis EventHandler heißt? Von allen verwirrenden Namenskonventionen ist dies die schlimmste ...
Joel in Gö
37
@Joel in Go das Ereignis heißt nicht EventHandler - EventHandler ist der Vertrag, den das Ereignis mit jedem haben muss, der mit ihm kommuniziert. Es ist wie "string MyString" - der String deklariert den Typ. Ereignis MyEventHandler TheEvent erklärt, dass jeder, der mit diesem Ereignis interagiert, dem MyEventHandler-Vertrag entsprechen muss. Die Handler-Konvention basiert darauf, dass der Vertrag in erster Linie beschreibt, wie das Ereignis behandelt wird.
Rex M
18
Wie wird das Ereignis ausgelöst?
Alchemie
17
@ Rex M: Danke für die erste zusammenhängende Erklärung für "MyEventHandler", die ich je gesehen habe :)
Joel in Gö
10
Vielen Dank für die Phase: "Der Klebstoff zwischen dem Ereignis und den auszuführenden Methoden sind die Delegierten.", Das ist wirklich großartig.
Zionpi
103

C # kennt zwei Begriffe delegateund event. Beginnen wir mit dem ersten.

Delegieren

A delegateist eine Referenz auf eine Methode. So wie Sie einen Verweis auf eine Instanz erstellen können:

MyClass instance = myFactory.GetInstance();

Sie können einen Delegaten verwenden, um einen Verweis auf eine Methode zu erstellen:

Action myMethod = myFactory.GetInstance;

Nachdem Sie diese Referenz auf eine Methode haben, können Sie die Methode über die Referenz aufrufen:

MyClass instance = myMethod();

Aber warum würdest du? Sie können auch einfach myFactory.GetInstance()direkt anrufen . In diesem Fall können Sie. Es gibt jedoch viele Fälle, in denen Sie darüber nachdenken müssen, wo der Rest der Anwendung keine Kenntnisse haben myFactoryoder anrufen sollmyFactory.GetInstance() direkt .

Ein offensichtlichste ist , wenn Sie ersetzen können , wollen myFactory.GetInstance()in myOfflineFakeFactory.GetInstance()von einem zentralen Ort (auch bekannt als Factory - Methode Mustern ).

Fabrikmethodenmuster

Wenn Sie also eine TheOtherClassKlasse haben und diese verwenden müssen myFactory.GetInstance(), sieht der Code ohne Delegaten folgendermaßen aus (Sie müssen TheOtherClassden Typ Ihrer Klasse angeben myFactory):

TheOtherClass toc;
//...
toc.SetFactory(myFactory);


class TheOtherClass
{
   public void SetFactory(MyFactory factory)
   {
      // set here
   }

}

Wenn Sie Delegaten verwenden möchten, müssen Sie den Typ meiner Fabrik nicht offenlegen:

TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);


class TheOtherClass
{
   public void SetFactoryMethod(Action factoryMethod)
   {
      // set here
   }

}

Auf diese Weise können Sie einen Delegaten einer anderen Klasse zur Verwendung zuweisen, ohne Ihren Typ für sie verfügbar zu machen. Das einzige, was Sie verfügbar machen, ist die Signatur Ihrer Methode (wie viele Parameter Sie haben und so).

"Unterschrift meiner Methode", wo habe ich das vorher gehört? O ja, Schnittstellen !!! Schnittstellen beschreiben die Signatur einer ganzen Klasse. Stellen Sie sich Delegierte so vor, als würden sie die Signatur nur einer Methode beschreiben!

Ein weiterer großer Unterschied zwischen einer Schnittstelle und einem Delegaten besteht darin, dass Sie beim Schreiben Ihrer Klasse C # nicht sagen müssen, dass diese Methode diesen Delegatentyp implementiert. Bei Schnittstellen müssen Sie sagen "Diese Klasse implementiert diesen Typ einer Schnittstelle".

Ferner kann eine Delegatenreferenz (mit einigen Einschränkungen, siehe unten) mehrere Methoden (aufgerufen) referenzieren MulticastDelegate ) . Dies bedeutet, dass beim Aufrufen des Delegaten mehrere explizit angehängte Methoden ausgeführt werden. Eine Objektreferenz kann immer nur auf ein Objekt verweisen.

Die Einschränkungen für a MulticastDelegatebestehen darin, dass die Signatur (Methode / Delegat) keinen Rückgabewert ( void) und die Schlüsselwörter haben sollte outund refnicht in der Signatur verwendet wird. Natürlich können Sie nicht zwei Methoden aufrufen, die eine Nummer zurückgeben, und erwarten, dass sie dieselbe Nummer zurückgeben. Sobald die Signatur übereinstimmt, ist der Delegat automatisch ein MulticastDelegate.

Veranstaltung

Ereignisse sind nur Eigenschaften (wie get; set; Eigenschaften für Instanzfelder), die das Abonnement für den Delegaten von anderen Objekten verfügbar machen. Diese Eigenschaften unterstützen get; set; jedoch nicht. Stattdessen unterstützen sie add; entfernen;

So können Sie haben:

    Action myField;

    public event Action MyProperty
    {
        add { myField += value; }
        remove { myField -= value; }
    }

Verwendung in der Benutzeroberfläche (WinForms, WPF, UWP usw.)

Jetzt wissen wir also, dass ein Delegat eine Referenz auf eine Methode ist und dass wir ein Ereignis haben können, um die Welt wissen zu lassen, dass sie uns ihre Methoden geben können, auf die von unserem Delegaten verwiesen werden kann, und wir sind dann eine UI-Schaltfläche: wir kann jeden, der daran interessiert ist, ob ich angeklickt wurde, bitten, seine Methode bei uns zu registrieren (über das Ereignis, das wir ausgesetzt haben). Wir können alle Methoden anwenden, die uns gegeben wurden, und sie von unserem Delegierten referenzieren. Und dann warten wir und warten ... bis ein Benutzer kommt und auf diese Schaltfläche klickt, dann haben wir genug Grund, den Delegaten aufzurufen. Und weil der Delegat auf alle uns gegebenen Methoden verweist, werden alle diese Methoden aufgerufen. Wir wissen nicht, was diese Methoden tun, und wir wissen auch nicht, welche Klasse diese Methoden implementiert. Wir kümmern uns nur darum, dass jemand daran interessiert war, dass wir angeklickt werden.

Java

Sprachen wie Java haben keine Delegierten. Sie verwenden stattdessen Schnittstellen. Sie bitten jeden, der daran interessiert ist, dass wir angeklickt werden, eine bestimmte Schnittstelle zu implementieren (mit einer bestimmten Methode, die wir aufrufen können), und geben dann die gesamte Instanz an, die die Schnittstelle implementiert. Wir führen eine Liste aller Objekte, die diese Schnittstelle implementieren, und können ihre "bestimmte Methode, die wir aufrufen können" aufrufen, wenn wir darauf klicken.

tofi9
quelle
Prost auf die Erklärung, aber wie unterscheidet sich ein Ereignis von einer Instanz eines Delegierten, der Abonnenten annimmt? sie sehen beide genau gleich aus?
BKSpurgeon
@BKSpurgeon das ist , weil sie sind „Delegierten , die auf Abonnenten nehmen“ - eventist nur Syntax Zucker, nicht mehr.
Mathieu Guindon
"Die Einschränkungen für ein MulticastDelegate bestehen darin, dass die Signatur (Methode / Delegat) keinen Rückgabewert (ungültig) haben sollte", halte ich dies nicht für richtig. Wenn sie Rückgabewerte haben, wird der letzte zurückgegeben.
Hozikimaru
"Auf diese Weise können Sie einen Delegaten einer anderen Klasse zur Verwendung geben, ohne Ihren Typ ihnen auszusetzen. Das einzige, was Sie aussetzen, ist die Signatur Ihrer Methode ..." - das ist für mich der kritische Punkt. Vielen Dank!
Ryan
40

Das ist eigentlich die Deklaration für einen Ereignishandler - eine Methode, die aufgerufen wird, wenn ein Ereignis ausgelöst wird. Um ein Ereignis zu erstellen, schreiben Sie Folgendes:

public class Foo
{
    public event EventHandler MyEvent;
}

Und dann können Sie die Veranstaltung folgendermaßen abonnieren:

Foo foo = new Foo();
foo.MyEvent += new EventHandler(this.OnMyEvent);

Mit OnMyEvent () wie folgt definiert:

private void OnMyEvent(object sender, EventArgs e)
{
    MessageBox.Show("MyEvent fired!");
}

Immer wenn es Foolosgeht MyEvent, wird Ihr OnMyEventHandler gerufen.

Sie müssen nicht immer eine Instanz von EventArgsals zweiten Parameter verwenden. Wenn Sie zusätzliche Informationen einschließen möchten, können Sie eine Klasse verwenden, die von EventArgs( EventArgsist die Basis gemäß Konvention) abgeleitet ist. Wenn Sie sich beispielsweise einige der Controlin WinForms oder FrameworkElementin WPF definierten Ereignisse ansehen , sehen Sie Beispiele für Ereignisse, die zusätzliche Informationen an die Ereignishandler übergeben.

Andy
quelle
14
Vielen Dank, dass Sie die Frage beantwortet haben und nicht an Delegierten und Veranstaltungen teilgenommen haben.
dividiere_byzero
3
Ich würde empfehlen, das OnXXXNamensmuster für Ihren Event-Handler nicht zu verwenden. (Dummerweise bedeutet OnXXX in MFC "Handle XXX" und in .net "XXX erhöhen". Daher ist seine Bedeutung jetzt unklar und verwirrend - siehe diesen Beitrag für Details ). Bevorzugte Namen wären das RaiseXXXAuslösen von Ereignissen und / HandleXXXoder Sender_XXXfür Ereignishandler.
Jason Williams
1
Können Sie ein funktionierendes Beispiel mit einer einfachen WinForms-Anwendung zeigen?
MC9000
40

Hier ist ein Codebeispiel, das helfen kann:

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

namespace Event_Example
{
  // First we have to define a delegate that acts as a signature for the
  // function that is ultimately called when the event is triggered.
  // You will notice that the second parameter is of MyEventArgs type.
  // This object will contain information about the triggered event.

  public delegate void MyEventHandler(object source, MyEventArgs e);

  // This is a class which describes the event to the class that receives it.
  // An EventArgs class must always derive from System.EventArgs.

  public class MyEventArgs : EventArgs
  {
    private string EventInfo;

    public MyEventArgs(string Text) {
      EventInfo = Text;
    }

    public string GetInfo() {
      return EventInfo;
    }
  }

  // This next class is the one which contains an event and triggers it
  // once an action is performed. For example, lets trigger this event
  // once a variable is incremented over a particular value. Notice the
  // event uses the MyEventHandler delegate to create a signature
  // for the called function.

  public class MyClass
  {
    public event MyEventHandler OnMaximum;

    private int i;
    private int Maximum = 10;

    public int MyValue
    {
      get { return i; }
      set
      {
        if(value <= Maximum) {
          i = value;
        }
        else 
        {
          // To make sure we only trigger the event if a handler is present
          // we check the event to make sure it's not null.
          if(OnMaximum != null) {
            OnMaximum(this, new MyEventArgs("You've entered " +
              value.ToString() +
              ", but the maximum is " +
              Maximum.ToString()));
          }
        }
      }
    }
  }

  class Program
  {
    // This is the actual method that will be assigned to the event handler
    // within the above class. This is where we perform an action once the
    // event has been triggered.

    static void MaximumReached(object source, MyEventArgs e) {
      Console.WriteLine(e.GetInfo());
    }

    static void Main(string[] args) {
      // Now lets test the event contained in the above class.
      MyClass MyObject = new MyClass();
      MyObject.OnMaximum += new MyEventHandler(MaximumReached);
      for(int x = 0; x <= 15; x++) {
        MyObject.MyValue = x;
      }
      Console.ReadLine();
    }
  }
}
Gary Willoughby
quelle
4
Der Aufruf von Delegierten kann in C # 6 vereinfacht werden, um:OnMaximum?.Invoke(this,new MyEventArgs("you've entered..."));
Tim Schmelter
23

Nur um die vorhandenen großartigen Antworten hier zu ergänzen - aufbauend auf dem Code in der akzeptierten, der delegate void MyEventHandler(string foo)...

Da der Compiler den Delegatentyp des SomethingHappened- Ereignisses kennt , gilt Folgendes:

myObj.SomethingHappened += HandleSomethingHappened;

Ist völlig gleichbedeutend mit:

myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);

Und Handler kann auch nicht registrierte mit -=wie folgt aus :

// -= removes the handler from the event's list of "listeners":
myObj.SomethingHappened -= HandleSomethingHappened;

Der Vollständigkeit halber kann das Auslösen des Ereignisses nur in der Klasse durchgeführt werden, der das Ereignis gehört:

//Firing the event is done by simply providing the arguments to the event:
var handler = SomethingHappened; // thread-local copy of the event
if (handler != null) // the event is null if there are no listeners!
{
    handler("Hi there!");
}

Der Thread-lokale Kopie des Handlers ist notwendig , um sicherzustellen , dass der Aufruf ist Thread-sicher - sonst könnte ein Thread gehen und austragen der letzten Prozedur für das Ereignis sofort , nachdem wir überprüft , ob es war null, und wir hätten einen „Spaß“ NullReferenceExceptiongibt .


C # 6 führte eine schöne kurze Hand für dieses Muster ein. Es verwendet den Null-Ausbreitungsoperator.

SomethingHappened?.Invoke("Hi there!");
Mathieu Guindon
quelle
13

Mein Verständnis der Ereignisse ist;

Delegieren:

Eine Variable, die einen Verweis auf die auszuführenden Methoden enthält. Dies ermöglicht es, Methoden wie eine Variable weiterzugeben.

Schritte zum Erstellen und Aufrufen des Ereignisses:

  1. Die Veranstaltung ist eine Instanz eines Delegaten

  2. Da ein Ereignis eine Instanz eines Delegaten ist, müssen wir zuerst den Delegaten definieren.

  3. Weisen Sie die Methode (n) zu, die ausgeführt werden sollen, wenn das Ereignis ausgelöst wird ( Aufruf des Delegaten )

  4. Ereignis auslösen ( Delegierten anrufen )

Beispiel:

using System;

namespace test{
    class MyTestApp{
        //The Event Handler declaration
        public delegate void EventHandler();

        //The Event declaration
        public event EventHandler MyHandler;

        //The method to call
        public void Hello(){
            Console.WriteLine("Hello World of events!");
        }

        public static void Main(){
            MyTestApp TestApp = new MyTestApp();

            //Assign the method to be called when the event is fired
            TestApp.MyHandler = new EventHandler(TestApp.Hello);

            //Firing the event
            if (TestApp.MyHandler != null){
                TestApp.MyHandler();
            }
        }

    }   

}
KE50
quelle
3

Herausgeber: Wo die Ereignisse stattfinden. Der Herausgeber sollte angeben, welchen Delegaten die Klasse verwendet, und die erforderlichen Argumente generieren, diese Argumente und sich selbst an den Delegaten übergeben.

Teilnehmer: Wo die Antwort erfolgt. Der Abonnent sollte Methoden angeben, um auf Ereignisse zu reagieren. Diese Methoden sollten die gleichen Argumente wie der Delegat verwenden. Der Abonnent fügt diese Methode dann dem Delegierten des Herausgebers hinzu.

Wenn das Ereignis im Herausgeber auftritt, erhält der Delegat daher einige Ereignisargumente (Daten usw.), aber der Herausgeber hat keine Ahnung, was mit all diesen Daten geschehen wird. Abonnenten können Methoden in ihrer eigenen Klasse erstellen, um auf Ereignisse in der Publisher-Klasse zu reagieren, sodass Abonnenten auf Publisher-Ereignisse reagieren können.

Rileyss
quelle
2
//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyDelegate(string foo);

//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyDelegate MyEvent;

//Here is some code I want to be executed
//when SomethingHappened fires.
void MyEventHandler(string foo)
{
    //Do some stuff
}

//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.MyEvent += new MyDelegate (MyEventHandler);
Bilgi Sayar
quelle
0

Ich stimme KE50 zu, außer dass ich das Schlüsselwort 'event' als Alias ​​für 'ActionCollection' betrachte, da das Ereignis eine Sammlung von auszuführenden Aktionen enthält (dh den Delegaten).

using System;

namespace test{

class MyTestApp{
    //The Event Handler declaration
    public delegate void EventAction();

    //The Event Action Collection 
    //Equivalent to 
    //  public List<EventAction> EventActions=new List<EventAction>();
    //        
    public event EventAction EventActions;

    //An Action
    public void Hello(){
        Console.WriteLine("Hello World of events!");
    }
    //Another Action
    public void Goodbye(){
        Console.WriteLine("Goodbye Cruel World of events!");
    }

    public static void Main(){
        MyTestApp TestApp = new MyTestApp();

        //Add actions to the collection
        TestApp.EventActions += TestApp.Hello;
        TestApp.EventActions += TestApp.Goodbye;

        //Invoke all event actions
        if (TestApp.EventActions!= null){
            //this peculiar syntax hides the invoke 
            TestApp.EventActions();
            //using the 'ActionCollection' idea:
            // foreach(EventAction action in TestApp.EventActions)
            //     action.Invoke();
        }
    }

}   

}
user3902302
quelle
0

Tolle technische Antworten in der Post! Ich habe technisch nichts hinzuzufügen.

Einer der Hauptgründe, warum neue Funktionen in Sprachen und Software im Allgemeinen erscheinen, ist Marketing oder Unternehmenspolitik! :-) Das darf nicht unterschätzt werden!

Ich denke, dies gilt in gewissem Umfang auch für Delegierte und Veranstaltungen! Ich finde sie nützlich und füge der C # -Sprache einen Mehrwert hinzu, aber andererseits hat die Java-Sprache beschlossen, sie nicht zu verwenden! Sie haben entschieden, dass alles, was Sie mit Delegierten lösen, bereits mit vorhandenen Funktionen der Sprache gelöst werden kann, z. B. Schnittstellen, z

Um 2001 herum veröffentlichte Microsoft das .NET-Framework und die C # -Sprache als Konkurrenzlösung für Java. Es war also gut, NEUE FUNKTIONEN zu haben, die Java nicht hat.

Siraf
quelle
0

Ich habe kürzlich ein Beispiel für die Verwendung von Ereignissen in c # erstellt und es in meinem Blog veröffentlicht. Ich habe versucht, es anhand eines sehr einfachen Beispiels so klar wie möglich zu machen. Falls es jemandem helfen könnte, hier ist es: http://www.konsfik.com/using-events-in-csharp/

Es enthält Beschreibung und Quellcode (mit vielen Kommentaren) und konzentriert sich hauptsächlich auf die ordnungsgemäße (vorlagenähnliche) Verwendung von Ereignissen und Ereignishandlern.

Einige wichtige Punkte sind:

  • Ereignisse sind wie "Untertypen von Delegierten", nur eingeschränkter (auf gute Weise). Tatsächlich enthält die Deklaration eines Ereignisses immer einen Delegaten (EventHandler sind eine Art Delegat).

  • Ereignishandler sind bestimmte Arten von Delegaten (Sie können sie als Vorlage betrachten), die den Benutzer dazu zwingen, Ereignisse mit einer bestimmten "Signatur" zu erstellen. Die Signatur hat das folgende Format: (Objektabsender, EventArgs-Ereignisargumente).

  • Sie können Ihre eigene Unterklasse von EventArgs erstellen, um alle Arten von Informationen aufzunehmen, die das Ereignis übermitteln muss. Es ist nicht erforderlich, EventHandler zu verwenden, wenn Ereignisse verwendet werden. Sie können sie vollständig überspringen und an ihrer Stelle Ihre eigene Art von Delegierten einsetzen.

  • Ein wesentlicher Unterschied zwischen der Verwendung von Ereignissen und Delegaten besteht darin, dass Ereignisse nur innerhalb der Klasse aufgerufen werden können, in der sie deklariert wurden, obwohl sie möglicherweise als öffentlich deklariert sind. Dies ist eine sehr wichtige Unterscheidung, da Ihre Ereignisse dadurch sichtbar gemacht werden können, dass sie mit externen Methoden "verbunden" sind, während sie gleichzeitig vor "externem Missbrauch" geschützt sind.

konsfik
quelle
0

Eine andere Sache, die Sie wissen sollten , in einigen Fällen müssen Sie die Delegaten / Ereignisse verwenden, wenn Sie ein geringes Maß an Kopplung benötigen !

Wenn Sie möchten , eine Komponente in mehrere in Anwendung verwenden , müssen Sie eine Komponente mit niedrigem Pegel zu koppeln und das spezifische machen unbeteiligt LOGIC muß delegiert werden OUTSIDE Ihrer Komponente! Dies stellt sicher, dass Sie ein entkoppeltes System und einen saubereren Code haben.

Im SOLID- Prinzip ist dies das " D " ( D. Ependenz-Inversionsprinzip).

Auch bekannt als " IoC ", Inversion of Control .

Sie können " IoC " mit Events, Delegates und DI erstellen (Dependency Injection) erstellen.

Es ist einfach, auf eine Methode in einer untergeordneten Klasse zuzugreifen. Es ist jedoch schwieriger, von einem Kind aus auf eine Methode in einer Elternklasse zuzugreifen. Sie müssen den Elternverweis an das Kind weitergeben! (oder DI mit Schnittstelle verwenden)

Mit Delegierten / Veranstaltungen können wir ohne Bezugnahme vom Kind zum Elternteil kommunizieren!

Geben Sie hier die Bildbeschreibung ein

In diesem Diagramm oben verwende ich Delegate / Event nicht und die übergeordnete Komponente B muss eine Referenz der übergeordneten Komponente A haben, um die nicht betroffene Geschäftslogik in Methode A auszuführen (hohe Kopplungsstufe).

Bei diesem Ansatz müsste ich alle Referenzen aller Komponenten einfügen, die Komponente B verwenden! :(

Geben Sie hier die Bildbeschreibung ein

In diesem Diagramm oben verwende ich Delegate / Event und die Komponente B muss A nicht kennen. (Geringe Kopplung)

Und Sie können Ihre Komponente B überall in Ihrer Anwendung verwenden !

A. Morel
quelle