C#delegate vs eventHandler

我想在发生陷阱时向任何订户通知警报消息。

我通过委托方法(myDelegate del)制作的代码很好。

我的问题是……

  1. 我想知道是否值得使用Eventhandler更好的代理? 在我的情况下,不确定委托和事件之间有什么不同?

  2. 通知(trapinfo t),这就是我在这里所做的,以获取陷阱信息。 但似乎不是一个好主意。 阅读一些介绍传递委托对象的在线教程课程,是否适合我的情况? 我该怎么办? 有什么建议?

非常感谢 :)

我的代码:

public class trapinfo { public string info; public string ip; public string cause; } public class trap { public delegate void myDelegate(trapinfo t); public myDelegate del; trapinfo info = new trapinfo(); public void run() { //While(true) // If a trap occurred, notify the subscriber for (; ; ) { Thread.Sleep(500); foreach (myDelegate d in del.GetInvocationList()) { info.cause = "Shut Down"; info.ip = "192.168.0.1"; info.info = "Test"; d.Invoke(info); } } } } public class machine { private int _occuredtime=0; public trapinfo info = new trapinfo(); public void notify(trapinfo t) { ++_occuredtime; info.cause = t.cause; info.info = t.info; info.ip = t.ip; getInfo(); } public void subscribe(trap t) { t.del += new trap.myDelegate(notify); } public void getInfo() { Console.WriteLine(": cauese/{0}, info/ {1}, ip/{2}, time/{3}", info.cause, info.info, info.ip,_occuredtime); } } class Program { static void Main(string[] args) { trap t = new trap(); machine machineA = new machine(); machineA.subscribe(t); t.run(); } } 

更新2013-08-12

观察者/可观察的设计模式怎么样,对我来说看起来很棒。 (EventHandler) 带代理的C#observer / observable的超简单示例

就我而言,一台机器订阅了一个陷阱信使。 (将计算机添加到调用列表)发生陷阱后,将消息发送到所有已订阅的计算机。 (调用HandleEvent来处理它)

优点:

  • 不再关心GetInvocationList(),只需使用(+ =)和( – =)来决定发送到哪个陷阱。

  • 轻松理解我的程序的逻辑。

我知道有几种方法可以做到,但我希望我能分析它的优点和缺点。 感谢您的意见和建议,这将非常有帮助!

我阅读了MSDN EventArgs文章,其中Matthew Watson建议使用system.eventargs

这是我的活动版本:

 public class TrapInfoEventArgs : EventArgs { public int info { get; set; } public string ip { get; set; } public string cause { get; set; } } public class trap { public event EventHandler TrapOccurred; protected virtual void OnTrapOccurred(TrapInfoEventArgs e) { EventHandler handler = TrapOccurred; if (handler != null) { handler(this, e); } } public void run() { //While(true) // If a trap occurred, notify the subscriber for (; ; ) { Thread.Sleep(500); TrapInfoEventArgs args = new TrapInfoEventArgs(); args.cause = "Shut Down"; OnTrapOccurred(args); } } } public class machine { public void c_TrapOccurred(object sender, TrapInfoEventArgs e) { Console.WriteLine(": cauese/{0}, info/ {1}, ip/{2}, time/{3}", e.cause, e.info, e.ip, DateTime.Now.ToString()); } } class Program { static void Main(string[] args) { trap t = new trap(); machine machineA = new machine(); t.TrapOccurred += machineA.c_TrapOccurred; //notify machine A t.run(); } } 

事件和委托之间的区别在于:

事件声明在委托实例上添加了一层保护。 此保护可防止委托的客户端重置委托及其调用列表,并且仅允许从调用列表中添加或删除目标

看看代表和活动之间有什么区别?

2)正如我所见,您的订阅者不应该自由更改委托。一个订阅者可以分配“=”而不是添加“+ =”。这将分配新的委托,因此,先前的委托及其调用列表将丢失,之前的订阅者将不再叫了。 所以你应该确定使用Event。 或者你可以改变你的代码,使你的委托私有,并编写额外的function来操纵它。所以这将是你自己的事件行为。

  //preventing direct assignment private myDelegate del ; public void AddCallback(myDelegate m){ del += m; } public void RemoveCallback(myDelegate m){ del -= m; } //or public static trap operator +(trap x,myDelegate m){ x.AddCallback(m); return x; } public static trap operator -(trap x, myDelegate m) { x.RemoveCallback(m); return x; } //usage //t.AddCallback(new trap.myDelegate(notify)); t+=new trap.myDelegate(notify); 

为您的示例使用event要好得多。

  • Visual Studio窗体和WPF设计器可以理解event ,因此您可以使用IDE订阅事件。

  • 在引发events ,您无需编写自己的foreach处理来迭代它们。

  • events是大多数程序员期望访问此function的方式。

  • 如果您使用委托,则使用代码可能会以您希望阻止的方式(例如重置其调用列表)来处理它。 events不允许这种情况发生。

至于你的第二个问题:使用一个event你将创建一个派生自EventArgs的类来保存数据,并在你引发它时将它传递给事件。 然后消费者可以访问它。

详情请见: http : //msdn.microsoft.com/en-us/library/system.eventargs.aspx