C# 委托Delegate、Action、Func和Event的区别

委托(Delegate) 是一种类型安全的函数指针,它允许你将方法(函数)作为参数传递、存储或动态调用。可以将委托看作成一个存放方法的容器,需要用到的时候可以在调用容器中的方法。

Delegate,Action,Func,Event的(ConsoleApplication)Demo1:

 public class ExerciseDelagate
    {

        public delegate void MyDelegate();    //声明一个无参数无返回值的委托

        public MyDelegate myDelegate; //初始化委托

        public Action<string> myAction; //直接初始化参数为string 无返回值的委托

        public Func<DateTime, string> myFunc; //直接初始化参数为DateTime 返回值string委托 ,返回类型为最后一个参数类型

        public event MyDelegate myEventDelegate;//event是基于委托的,初始化事件


        public void DelegateExample()
        {
            Console.Write("我是Delegate委托赋予的方法\n");
        }

        public void ActionExample(string str)
        {
            Console.Write($"我是Action委托赋予的方法-{str}\n");
        }

        public string FuncExample(DateTime dateTime)
        {
            return string.Format("我是Func委托赋予的方法-{0}\n", dateTime);
        }
        public void DelegateExample2()
        {
            Console.Write("我是Delegate多播委托的实例\n");
        }
        public void EventExample()
        {
          
            Console.Write("我是Event实例方法\n");
        }

        public void CallEvent()
        {
            myEventDelegate?.Invoke();//用?.invoke()可以防止myEventDelegate没绑定方法直接调用
        }

    }
    public class Demo
    {
        static void Main(string[] args)
        {
            
            ExerciseDelagate exdelegate =   new ExerciseDelagate();
            exdelegate.myDelegate = exdelegate.DelegateExample;     //绑定实例方法,方法的参数和返回值要与委托一致
            exdelegate.myDelegate += exdelegate.DelegateExample2;   //可以绑定多个方法,称为多播委托 用+= 增加,-=减少
            exdelegate.myDelegate();                                //调用委托,相当于调用DelegateExample和DelegateExample2方法。
            //exdelegate.myDelegate?.Invoke();                      也可以写成这样,与上面执行结果一致

            exdelegate.myAction = exdelegate.ActionExample;         //绑定实例方法,方法的参数和返回值要与委托一致
            exdelegate.myAction("Hello");                           //调用委托,相当于调用ActionExample方法。

            exdelegate.myFunc = exdelegate.FuncExample;             //绑定实例方法,方法的参数和返回值要与委托一致
            Console.Write(exdelegate.myFunc(DateTime.Now));         //调用委托,相当于调用FuncExample方法获取返回值再打印出来。


            //exdelegate.myEventDelegate = exdelegate.EveneExample;   //注意事件不能用'='绑定方法,过不了编译 只能用+=或者-=
            exdelegate.myEventDelegate += exdelegate.EventExample;    //原因是event关键字保证了对应类内部的安全和封装,避免覆盖类里的绑定方法
            //exdelegate.myEventDelegate();                           //注意事件也不能由外部调用,过不了编译
            exdelegate.CallEvent();                                   //调用CallEvent方法间接去实现事件

            Console.ReadLine();


        }

    }

在平时开发中,应用到委托的场景有窗体之间的传值等,如在Form1中的业务逻辑需要传值取构建Form2,Form2执行完逻辑用户在关闭Form2后需要返回值给Form1。窗体传值Demo2:

我们想在Form关闭后Form1的标题值改成返回值,Form1代码:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 form2= new Form2(DateTime.Now);           //构造Form2
            form2.dataReturned += Form2DataReturn;          //事件绑定Form2DataReturn方法
            form2.Show();
        }

        private void Form2DataReturn(string obj)
        {
            this.Text = obj;
        }
    }

Form2代码:

public partial class Form2 : Form
    {
        private DateTime dateTime;

        private string dataTimeStr;


        public event Action<string> dataReturned;  //初始化事件 无返回值有string类型参数


        public Form2(DateTime now)
        {
            InitializeComponent();
            this.FormClosed += Form2_FormClosed;        //Form2关闭窗体事件绑定方法,也可以在前端绑定,效果一样,不过前端绑定这条代码会自动放在InitializeComponent()里
            this.dateTime = now;
        }

        private void Form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            
            dataReturned?.Invoke(dataTimeStr); //将处理后的业务结果作为参数放回
        }
        /// <summary>
        /// 窗体加载事件方法,这段就是在前端绑定的方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form2_Load(object sender, EventArgs e)
        {
            //处理返回值的业务逻辑,这里简单化
            dataTimeStr= this.dateTime.ToString("yyyy-MM-dd");
        }
    }

点击打开Form2按钮                                                                                                                                        Form2关闭后,Form1标题就改变了

日志记录Demo3:

Form1代码:

 public partial class Form1 : Form
    {
        public static Action<string> addLog;
 

        public Form1()
        {
            InitializeComponent();
            addLog = WriteListViewLog;  
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 form2= new Form2(DateTime.Now);           //构造Form2
            form2.dataReturned += Form2DataReturn;          //事件绑定Form2DataReturn方法
            form2.Show();
        }

        private void Form2DataReturn(string obj)
        {
            this.Text = obj;
        }

        /// <summary>
        /// listView 日志写入方法
        /// </summary>
        private  void WriteListViewLog(string logStr)
        {
            //InvokeRequired判断是否在UI线程上执行,如果不在则用控件.invoke将指定的委托排队到创建该控件的UI线程的消息队列中,并在该UI线程上执行该委托。
            if (this.InvokeRequired)
            {
                this.listView1.Invoke(new Action<string>(WriteListViewLog),logStr);

            }
            ListViewItem listViewItem = new ListViewItem(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            listViewItem.SubItems.Add(logStr);
            this.listView1.Items.Add(listViewItem);
        }


    }

Form2:

   public partial class Form2 : Form
    {
        private DateTime dateTime;

        private string dataTimeStr;


        public event Action<string> dataReturned;  //初始化事件 无返回值有string类型参数


        public Form2(DateTime now)
        {
            InitializeComponent();
            this.FormClosed += Form2_FormClosed;        //Form2关闭窗体事件绑定方法,也可以在前端绑定,效果一样,不过前端绑定这条代码会自动放在InitializeComponent()里
            this.dateTime = now;
        }

        private void Form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            
            dataReturned?.Invoke(dataTimeStr); //将处理后的业务结果作为参数放回
        }
        /// <summary>
        /// 窗体加载事件方法,这段就是在前端绑定的方法
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form2_Load(object sender, EventArgs e)
        {
            Form1.addLog("成功打开Form2窗体");
            //处理返回值的业务逻辑,这里简单化
            dataTimeStr = this.dateTime.ToString("yyyy-MM-dd");
        }
    }

打开FORM1                                                                                                         打开FOMR2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值