C# Event Action与Invoke

2023-05-16

趁着1024这个好日子来讲一下

通常在C# 中
为了将功能模块化
我们会把重复使用的功能写到类 (Class)里面
但是写在类里面的方法是无法直接对主窗体界面进行操作的
这个时候我们就需要使用 “委托”
关于委托的讲解可以参考这篇
https://www.cnblogs.com/wudiwushen/archive/2010/04/20/1703368.html
讲的挺浅显易懂的
但随着时代的进步
程式语言也在进步(人越来越懒)

现在我们只需要在类中声明一个Event Action的变量
就可以让随时呼叫并执行我们在主界面的方法
而主界面的方法就可以对界面进行操作拉

class Class1
    {
        public event Action Call;  <--记得要用public才找得到
        public void Show()
        {
            Call.Invoke();
        }
    }
Form1
   public partial class Form1 : Form
    {
        Class1 c1;
        public Form1()
        {
            InitializeComponent();

        }
        private void Form1_Load(object sender, EventArgs e)
        {
            c1 = new Class1();
            c1.Call += Called;  <---注意这里
        }
        private void Called()
        {
            label1.Text = "123";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            c1.Show();   <--会在Show里面invoke到Called
        }
    }

Form1中+=使用的就是一个委托的概念
意思是当c1 这个object(类的实例化)里面的Call (呼叫)这个Event Action的时候
会呼叫到Form1 (主界面)中的Called (被呼叫)方法
在这里插入图片描述
在这里插入图片描述
这个时候的顺序应该是

  1. 按下button1
  2. 执行c1.show()
  3. show方法中执行Call.Invoke()
  4. Call.Invoke()呼叫Called方法执行 (因为 c1.Call += Called这句)
  5. 执行Called方法
  6. 将Label1的文字修改为 “123”

那么若是
多了一个button里头执行

    private void button2_Click(object sender, EventArgs e)
        {
            c1.Call -= Called;
        }

会发生什么事?
在这里插入图片描述
我们再理清一下顺序

  1. 按下button1
  2. 执行c1.show()
  3. show方法中执行Call.Invoke()
  4. Call.Invoke()呼叫Called方法执行 (因为 c1.Call += Called这句)
  5. 执行Called方法
  6. 将Label1的文字修改为 “123”
    --------到这边位置都一样--------
  7. 按下button2 (c1.Call -= Called 取消注册)
  8. 按下button1
  9. 执行c1.show()
  10. show方法中执行Call.Invoke()
  11. 因为Call并没有注册任何的方法,系统不知道要呼叫谁就报错了

那有没有方法避免呢? 是有的

  public void Show()
        {
            Call?.Invoke();
        }

看得出来差在哪里吗?
其实就只加了一个?上去而已
但这个问号在的功用等于

 if (Call != null) { Call.invoke();}

因为Call并未注册 (被取消注册) 所以没有任何值或地址在里面
所以便不会执行Call.Invoke()了

再来 如果我们要将变量透过invoke()传递该怎么做呢?
很简单

public event Action<string> Call;  <--代表呼叫接收一个string的方法
        public void Show()
        {
            string text = "456";
            Call?.Invoke(text);
        }
Form1
 Class1 c1;
        public Form1()
        {
            InitializeComponent();

        }
        private void Form1_Load(object sender, EventArgs e)
        {
            c1 = new Class1();
            c1.Call += Called;
        }
        private void Called(string text)  <--接收一个string
        {
            label1.Text = text;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            c1.Show();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            c1.Call -= Called;
        }

在这里插入图片描述

当然 你也可以不只传递一个参数

 public event Action<int, string, string> Call;
        public void Show()
        {
            int time = 2;
            string text1 = "456";
            string text2 = "789";
            Call?.Invoke(time, text1, text2);
        }
 Class1 c1;
        public Form1()
        {
            InitializeComponent();

        }
        private void Form1_Load(object sender, EventArgs e)
        {
            c1 = new Class1();
            c1.Call += Called;
        }
        private void Called(int time, string text1, string text2)
        {
            for(int i=0; i<time; i++)
            {
                label1.Text += text1;
                label1.Text += text2;
                label1.Text += "x";
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            c1.Show();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            c1.Call -= Called;
        }

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# Event Action与Invoke 的相关文章

随机推荐