Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#代表v.s.事件处理程序_C#_Delegates_Event Handling_Observer Pattern - Fatal编程技术网

C#代表v.s.事件处理程序

C#代表v.s.事件处理程序,c#,delegates,event-handling,observer-pattern,C#,Delegates,Event Handling,Observer Pattern,我想在陷阱发生时向所有订户发送警报消息 我创建的代码使用委托方法myDelegate可以很好地工作 我的问题是: 我想知道是否最好使用EventHandler而不是委托? 在我的例子中,我不确定委托和EventHandler之间有什么区别 notify(trapinfot),这就是我在这里获取陷阱信息所做的。但这似乎不是一个好主意。我读了一些在线教程,介绍如何传递代理对象;我想知道这对我来说是否合适?我该怎么做呢?有什么建议吗 非常感谢:) 我的代码: public class trapinfo

我想在陷阱发生时向所有订户发送警报消息

我创建的代码使用委托方法
myDelegate
可以很好地工作

我的问题是:

  • 我想知道是否最好使用
    EventHandler
    而不是委托? 在我的例子中,我不确定委托和
    EventHandler
    之间有什么区别

  • notify(trapinfot)
    ,这就是我在这里获取陷阱信息所做的。但这似乎不是一个好主意。我读了一些在线教程,介绍如何传递代理对象;我想知道这对我来说是否合适?我该怎么做呢?有什么建议吗

  • 非常感谢:)

    我的代码:

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

    对于您的示例,最好使用
    事件

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

    • 当引发
      事件时
      ,您无需编写自己的
      foreach
      处理来迭代它们

    • 事件
      是大多数程序员希望访问此功能的方式

    • 如果使用委托,消费代码可能会以您希望防止的方式(例如重置其调用列表)干扰委托<代码>事件不允许发生这种情况

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


    有关详细信息,请参见此处:

    事件和委托的区别在于:

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

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

    所以我必须在我发布的代码中处理调用列表,是吗?您需要提供函数来更改它,而不是直接访问它。OOP封装概念可能重复