C#delegate vs eventHandler

Hsu*_*eng 20 c# delegates event-handling observer-pattern

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

我通过委托方法(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("<Alert>: 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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

更新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<TrapInfoEventArgs> TrapOccurred;

    protected virtual void OnTrapOccurred(TrapInfoEventArgs e)
    {
        EventHandler<TrapInfoEventArgs> 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("<Alert>: 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

qwr*_*qwr 18

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

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

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

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

 //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);
Run Code Online (Sandbox Code Playgroud)


Mat*_*son 8

最好使用一个event例子.

  • 一个event由Visual Studio的窗体和WPF设计的理解,所以你可以使用IDE订阅事件.

  • 在提升时events,您无需编写自己的foreach处理来迭代它们.

  • events 是大多数程序员期望访问此功能的方式.

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

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

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