事件学习一:直接事件模型+委托

文章参考总结一下博客

解惑答疑:C#委托和事件 - 51CTO.COM

C#中的委托和事件(续) - Jimmy Zhang - 博客园 (cnblogs.com)

C#中委托和事件的区别 - Darren Ji - 博客园 (cnblogs.com)

委托和事件_前路漫漫其修远兮的博客-CSDN博客

C#中委托、事件和回调函数的理解 - 每天进步多一点 - 博客园 (cnblogs.com)

1.通过委托来执行方法

    delegate int Transformer(int i);
    class Program
    {
        static void Main(string[] args)
        {
            Transformer t = Square;
            int result = t(2);
            Console.Read();
        } 
        static int Square(int a)
        {
            return a * a;
        }
    }
View Code

所有委托都有多播能力,可以使用+=运算符联结多个委托实例。

Transformer t = Square1;

t += Square2;

委托是不可变的,调用+=和-=实质上是创建一个委托实例,并把它赋给已有变量。

C#委托和事件的使用示例 - vickylinj - 博客园 (cnblogs.com)可以看委托的使用。

2.通过事件来执行方法

事件是一种使用有限的委托功能实现广播(发布)者/订阅者模型的结构,使用事件的主要目的是保证订阅者之间部相互干扰。事件自身就是委托类型

  • 发布者是指拥有某事件的类或者结构
  • 订阅者是指向发布者注册的类或者结构
  • 事件处理程序是指由订阅者注册到事件的方法,在发布者触发事件时执行

摘自C#沉淀-事件:发布订阅模式_东南有大树的博客-CSDN博客_c# 发布订阅模式

标准事件模式

    class Model
    {
        public Model(int a1)
        {
            MyProperty = a1;
        }
        public int MyProperty { get; set; }  
    }
    class Stock//它就是广播者
    {
        public event EventHandler<Model> ModelEvent;
        protected virtual void OnModelEvent(Model e)
        {
            ModelEvent?.Invoke(this, e);//第一个参数表示事件的广播者,e表示需要传递的额外信息
        }
        private int price;
        public int Price
        {
            get
            {
                return price;
            }
            set
            {
                if (price == value)
                    return;
                price = value;
                OnModelEvent(new Model(price));//属性改变了的时候通知订阅者
            }
        }
    }

    class Program
    {
        
        static void Main(string[] args)
        {
            Stock stock = new Stock();
            stock.ModelEvent += stock_ModelEvent;
            stock.Price = 8;//改变
            Console.Read();
        } 
        static void stock_ModelEvent(object sender,Model e)
        {
            Console.WriteLine(e.MyProperty);
        }
}

 通过如上可以引出----当一个类中的数据改变时可以使用事件来通知另外的一个类。

class Model
    {
        public Model(int a1)
        {
            MyProperty = a1;
        }
        public int MyProperty { get; set; }  
    }
    class Stock
    {
        public event EventHandler<Model> ModelEvent;
        protected virtual void OnModelEvent(Model e)
        {
            ModelEvent?.Invoke(this, e);//第一个参数表示事件的广播者,e表示需要传递的额外信息
        }
        Thread thread1;
        public void Start()
        {
            thread1 = new Thread(new ThreadStart(Method));
            thread1.IsBackground = true;
            thread1.Start();
        }
        void Method()
        {
            
            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(1000);
                OnModelEvent(new Model(i));//属性改变了的时候通知订阅者
            }
        }        
    }

       static void Main(string[] args)
        {
            Stock stock = new Stock();
            stock.ModelEvent += stock_ModelEvent;
            stock.Start();
            Console.Read();
        } 
        static void stock_ModelEvent(object sender,Model e)
        {
            Console.WriteLine(e.MyProperty);
        }
View Code

通过上诉还可引出---该通知功能还可以用在线程中。

有了委托为什么还要有事件??摘自C#中的委托与事件并存的理由 - ____轨迹 - 博客园 (cnblogs.com)

委托可被任意调用者修改,甚至抹去所有的委托链,而对于事件,只能由订阅者自己决定订阅或者移除事件。事件的密封性较好,他从本质层面上反映出了事件是属于发布者的,订阅者只能决定自己订阅的事件,不能影响发布者

的所有订阅对象。你为了反映这一事实,就不能使用委托来替代。

 

举例1:通过委托和事件实现窗口之间的传值

子窗口

public delegate void ChildFormHandler(string value);
    public partial class ChildForm : Form
    {     
        public event ChildFormHandler ChildFormEvent;
        public ChildForm()
        {
            InitializeComponent();
        }

        private void btnChild_Click(object sender, EventArgs e)
        {
            ChildFormEvent("a");//执行第一步
            this.Close();//执行第三步
          
        }
    }
View Code

父窗口

 private void btnParent_Click(object sender, EventArgs e)
        {
            ChildForm childForm = new ChildForm();
            childForm.ChildFormEvent += new ChildFormHandler(Method);
            childForm.Show();
        }
        void Method(string value)//执行第二步
        {

        }
View Code

总结:

○ 委托就是一个类,也可以实例化,通过委托的构造函数来把方法赋值给委托实例
○ 触发委托有2种方式: 委托实例.Invoke(参数列表),委托实例(参数列表)
○ 事件是一个用event关键字修饰的委托类型的变量
○ 通过+=为事件注册多个委托实例或多个方法
○ 通过-=为事件注销多个委托实例或多个方法
○ EventHandler就是一个委托

委托较直接调用方法优点:

1.相当于用方法作为另一方法参数(类似于C的函数指针)
2.在两个不能直接调用的方法中作为桥梁,如:在跨线程的方法调用就得用委托
3.当不知道方法具体实现什么时使用委托,如:事件中使用委托
4.解耦

直接事件模型的缺点:

1.程序运行期在容器中动态生成一组相同控件的时候,需要显示书写事件订阅代码。

2.当户控件的内部事件不能被外界所订阅,必须为用户控件定义新的事件用以向外界暴露内部事件。

posted @ 2021-11-03 00:08  HelloWorld庄先生  阅读(88)  评论(0编辑  收藏  举报