Was sind die Unterschiede zwischen Delegierten und einem Ereignis? Enthalten nicht beide Verweise auf Funktionen, die ausgeführt werden können?
Antworten
Zu viele Anzeigen?Ein Ereignis in .net ist eine bestimmte Kombination aus einer Add-Methode und einer Remove-Methode, die beide einen bestimmten Typ von Delegaten erwarten. Sowohl C# als auch VB.net können automatisch Code für die Add- und Remove-Methoden generieren, der einen Delegaten für die Ereignisabonnements definiert und den übergebenen Delegaten zu diesem Abonnementdelegaten hinzufügt bzw. von diesem entfernt. VB.net generiert auch automatisch Code (mit der Anweisung RaiseEvent), um die Abonnementliste aufzurufen, wenn und nur wenn es nicht leer ist; aus irgendeinem Grund, C# generiert letzteres nicht.
Beachten Sie, dass es zwar üblich ist, Ereignisabonnements mit einem Multicast-Delegaten zu verwalten, dies aber nicht die einzige Möglichkeit ist. Aus der Sicht der Öffentlichkeit muss ein potenzieller Ereignisabonnent wissen, wie er ein Objekt wissen lässt, dass er Ereignisse empfangen möchte, aber er muss nicht wissen, welchen Mechanismus der Herausgeber verwenden wird, um die Ereignisse auszulösen. Beachten Sie auch, dass derjenige, der die Ereignisdatenstruktur in .net definiert hat, offenbar der Meinung war, dass es ein öffentliches Mittel zum Auslösen von Ereignissen geben sollte, aber weder C# noch vb.net machen von dieser Möglichkeit Gebrauch.
Die Definition eines Ereignisses ist einfach:
Veranstaltung ist eine REFERENZ an einen Delegierten mit zwei Einschränkungen
- Kann nicht direkt aufgerufen werden
- Kann nicht direkt mit Werten belegt werden (z.B. eventObj = delegateMethod)
Die beiden oben genannten Punkte sind die Schwachstellen der Delegierten und werden in der Veranstaltung angesprochen. Ein vollständiges Codebeispiel, das den Unterschied in Fiddler zeigt, finden Sie hier https://dotnetfiddle.net/5iR3fB .
Schalten Sie den Kommentar zwischen Ereignis und Delegat und Client-Code, der den Delegaten Werte zuweist, um den Unterschied zu verstehen
Hier ist der Inline-Code.
/*
This is working program in Visual Studio. It is not running in fiddler because of infinite loop in code.
This code demonstrates the difference between event and delegate
Event is an delegate reference with two restrictions for increased protection
1. Cannot be invoked directly
2. Cannot assign value to delegate reference directly
Toggle between Event vs Delegate in the code by commenting/un commenting the relevant lines
*/
public class RoomTemperatureController
{
private int _roomTemperature = 25;//Default/Starting room Temperature
private bool _isAirConditionTurnedOn = false;//Default AC is Off
private bool _isHeatTurnedOn = false;//Default Heat is Off
private bool _tempSimulator = false;
public delegate void OnRoomTemperatureChange(int roomTemperature); //OnRoomTemperatureChange is a type of Delegate (Check next line for proof)
// public OnRoomTemperatureChange WhenRoomTemperatureChange;// { get; set; }//Exposing the delegate to outside world, cannot directly expose the delegate (line above),
public event OnRoomTemperatureChange WhenRoomTemperatureChange;// { get; set; }//Exposing the delegate to outside world, cannot directly expose the delegate (line above),
public RoomTemperatureController()
{
WhenRoomTemperatureChange += InternalRoomTemperatuerHandler;
}
private void InternalRoomTemperatuerHandler(int roomTemp)
{
System.Console.WriteLine("Internal Room Temperature Handler - Mandatory to handle/ Should not be removed by external consumer of ths class: Note, if it is delegate this can be removed, if event cannot be removed");
}
//User cannot directly asign values to delegate (e.g. roomTempControllerObj.OnRoomTemperatureChange = delegateMethod (System will throw error)
public bool TurnRoomTeperatureSimulator
{
set
{
_tempSimulator = value;
if (value)
{
SimulateRoomTemperature(); //Turn on Simulator
}
}
get { return _tempSimulator; }
}
public void TurnAirCondition(bool val)
{
_isAirConditionTurnedOn = val;
_isHeatTurnedOn = !val;//Binary switch If Heat is ON - AC will turned off automatically (binary)
System.Console.WriteLine("Aircondition :" + _isAirConditionTurnedOn);
System.Console.WriteLine("Heat :" + _isHeatTurnedOn);
}
public void TurnHeat(bool val)
{
_isHeatTurnedOn = val;
_isAirConditionTurnedOn = !val;//Binary switch If Heat is ON - AC will turned off automatically (binary)
System.Console.WriteLine("Aircondition :" + _isAirConditionTurnedOn);
System.Console.WriteLine("Heat :" + _isHeatTurnedOn);
}
public async void SimulateRoomTemperature()
{
while (_tempSimulator)
{
if (_isAirConditionTurnedOn)
_roomTemperature--;//Decrease Room Temperature if AC is turned On
if (_isHeatTurnedOn)
_roomTemperature++;//Decrease Room Temperature if AC is turned On
System.Console.WriteLine("Temperature :" + _roomTemperature);
if (WhenRoomTemperatureChange != null)
WhenRoomTemperatureChange(_roomTemperature);
System.Threading.Thread.Sleep(500);//Every second Temperature changes based on AC/Heat Status
}
}
}
public class MySweetHome
{
RoomTemperatureController roomController = null;
public MySweetHome()
{
roomController = new RoomTemperatureController();
roomController.WhenRoomTemperatureChange += TurnHeatOrACBasedOnTemp;
//roomController.WhenRoomTemperatureChange = null; //Setting NULL to delegate reference is possible where as for Event it is not possible.
//roomController.WhenRoomTemperatureChange.DynamicInvoke();//Dynamic Invoke is possible for Delgate and not possible with Event
roomController.SimulateRoomTemperature();
System.Threading.Thread.Sleep(5000);
roomController.TurnAirCondition (true);
roomController.TurnRoomTeperatureSimulator = true;
}
public void TurnHeatOrACBasedOnTemp(int temp)
{
if (temp >= 30)
roomController.TurnAirCondition(true);
if (temp <= 15)
roomController.TurnHeat(true);
}
public static void Main(string []args)
{
MySweetHome home = new MySweetHome();
}
}
Für Menschen, die im Jahr 2020 leben und eine saubere Antwort wollen...
Definitionen:
delegate
: definiert einen Funktionszeiger.event
: definiert- (1) geschützt Schnittstellen, と
- (2) Operationen(
+=
,-=
), と - (3) Vorteil: Sie müssen nicht die
new
Stichwort nicht mehr.
Bezüglich des Adjektivs geschützt :
// eventTest.SomeoneSay = null; // Compile Error.
// eventTest.SomeoneSay = new Say(SayHello); // Compile Error.
Beachten Sie auch diesen Abschnitt von Microsoft: https://docs.microsoft.com/en-us/dotnet/standard/events/#raising-multiple-events
Code-Beispiel:
avec delegate
:
public class DelegateTest
{
public delegate void Say(); // Define a pointer type "void <- ()" named "Say".
private Say say;
public DelegateTest() {
say = new Say(SayHello); // Setup the field, Say say, first.
say += new Say(SayGoodBye);
say.Invoke();
}
public void SayHello() { /* display "Hello World!" to your GUI. */ }
public void SayGoodBye() { /* display "Good bye!" to your GUI. */ }
}
avec event
:
public class EventTest
{
public delegate void Say();
public event Say SomeoneSay; // Use the type "Say" to define event, an
// auto-setup-everything-good field for you.
public EventTest() {
SomeoneSay += SayHello;
SomeoneSay += SayGoodBye;
SomeoneSay();
}
public void SayHello() { /* display "Hello World!" to your GUI. */ }
public void SayGoodBye() { /* display "Good bye!" to your GUI. */ }
}
Referenz:
Ereignis vs. Delegierter - Erläuterung der wichtigen Unterschiede zwischen dem Ereignis- und dem Delegate-Muster in C# und warum sie nützlich sind. : https://dzone.com/articles/event-vs-delegate
- See previous answers
- Weitere Antworten anzeigen