.net event - Ereignisse und Ereignishandler in C#verstehen




eventhandler eventargs (9)

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

public void EventName(object sender, EventArgs e);

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


Answers

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

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

}   

}

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

public class Foo
{
    public event EventHandler MyEvent;
}

Und dann können Sie die Veranstaltung wie folgt abonnieren:

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

Mit OnMyEvent () definiert wie folgt:

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

Immer wenn Foo MyEvent , wird Ihr OnMyEvent Handler aufgerufen.

Sie müssen nicht immer eine Instanz von EventArgs als zweiten Parameter verwenden. Wenn Sie zusätzliche Informationen EventArgs EventArgs , können Sie eine von EventArgs abgeleitete Klasse EventArgs ( EventArgs ist die Basis nach Konvention). Wenn Sie sich beispielsweise einige Ereignisse ansehen, die unter Control in WinForms oder FrameworkElement in WPF definiert sind, können Sie Beispiele für Ereignisse sehen, die zusätzliche Informationen an die Ereignisbehandlungsroutinen übergeben.


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

Herausgeber: Wo die Ereignisse passieren. Der Publisher sollte angeben, welcher Delegat die Klasse verwendet und die erforderlichen Argumente generiert. Übergeben Sie diese Argumente und selbst an den Delegaten.

Teilnehmer: Wo die Antwort passiert. Der Abonnent sollte Methoden angeben, um auf Ereignisse zu reagieren. Diese Methoden sollten denselben Typ von Argumenten wie der Delegat verwenden. Abonnent fügt diese Methode dem Verlegerdelegierten hinzu.

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


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

Um Event-Handler zu verstehen, müssen Sie delegates verstehen. In C# können Sie sich einen Delegaten als Zeiger (oder Verweis) 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 void MyDelegate(object sender, EventArgs e) , kann er nur auf Methoden verweisen, die void und ein object und EventArgs . Ein bisschen wie ein quadratisches Loch und ein quadratischer Pflock. Wir sagen also, diese Methoden haben die gleiche Signatur oder Form wie der Delegierte.

Wenn wir wissen, wie man einen Verweis auf eine Methode erstellt, denken wir über den Zweck von Ereignissen nach: Wir möchten, dass ein bestimmter Code ausgeführt wird, wenn etwas anderswo im System passiert - oder "das Ereignis behandeln". Dazu erstellen wir spezifische Methoden für den Code, der ausgeführt werden soll. Das Bindeglied zwischen dem Ereignis und den auszuführenden Methoden sind die Delegierten. Das Ereignis muss intern eine "Liste" von Zeigern zu den Methoden enthalten, die aufgerufen werden, wenn das Ereignis ausgelöst wird. * Um eine Methode aufrufen zu können, müssen wir natürlich wissen, welche Argumente übergeben werden müssen! Wir verwenden den Delegaten als "Vertrag" zwischen dem Ereignis und allen spezifischen Methoden, die aufgerufen werden.

So stellt der Standard- EventHandler (und viele ähnliche) eine bestimmte Form der Methode dar (wiederum void / object-EventArgs). Wenn Sie ein Ereignis deklarieren, sagen Sie, welche Form der Methode (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.
MyEventHandler("bar");

(* Dies ist der Schlüssel zu Ereignissen in .NET und entfernt die "Magie" - ein Ereignis ist wirklich, unter der Decke, nur eine Liste von Methoden der gleichen "Form". Die Liste wird dort gespeichert, wo das Ereignis lebt Das Ereignis ist "ausgelöst", es ist wirklich nur "gehen Sie durch diese Liste von Methoden und rufen Sie jedes, mit diesen Werten als Parameter." Zuweisen eines Ereignishandlers ist nur ein schöner, einfacher Weg, Ihre Methode zu dieser Liste von Methoden hinzuzufügen heißen).


Mein Verständnis der Ereignisse ist;

Delegieren:

Eine Variable, die eine Referenz auf die auszuführende Methode / Methoden enthält. Dies ermöglicht es, Methoden wie eine Variable zu umgehen.

Schritte zum Erstellen und Aufrufen des Ereignisses:

  1. Das Ereignis 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 / Methoden zu, die ausgeführt werden sollen, wenn das Ereignis ausgelöst wird ( Aufruf des Delegaten )

  4. Feuern Sie das Ereignis ab ( Rufen Sie den Delegierten an )

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

    }   

}

Nur um die bestehenden großen Antworten hier hinzuzufügen - aufbauend auf dem Code in der akzeptierten, die einen delegate void MyEventHandler(string foo) ...

Weil der Compiler den Delegattyp des SomethingHappened- Ereignisses kennt:

myObj.SomethingHappened += HandleSomethingHappened;

Ist völlig äquivalent zu:

myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);

Und Handler können auch mit -= aufgehoben werden:

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

Der Vollständigkeit halber kann das Hochfahren des Ereignisses nur in der Klasse durchgeführt werden, die das Ereignis besitzt:

//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!");
}

Die thread-lokale Kopie des Handlers wird benötigt, um sicherzustellen, dass der Aufruf Thread-sicher ist - andernfalls könnte ein Thread den letzten Handler für das Ereignis entfernen, nachdem wir überprüft haben, ob es null , und wir würden einen "Spaß" haben NullReferenceException dort.

C # 6 hat eine nette kurze Hand für dieses Muster eingeführt. Es verwendet den Null-Propagierungsoperator.

SomethingHappened?.Invoke("Hi there!");

  • C # 1.0 mit Visual Studio.NET

  • C # 2.0 mit Visual Studio 2005

  • C # 3.0 mit Visual Studio 2008

  • C # 4.0 mit Visual Studio 2010

  • C # 5.0 mit Visual Studio 2012

  • C # 6.0 mit Visual Studio 2015

  • C # 7.0 mit Visual Studio 2017







c# .net events event-handling