首页 > 技术文章 > C#委托 delegate,Action,Func,事件

yunnn 2022-03-02 15:24 原文

1 delegate

1.1 delegate委托声明 Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型。
注意 delegate必须实例化 声明的参数和返回值没有限制 但是委托的方法必须和委托的类型一致
1.2 附代码

先声明delegate和一个方法

        /// <summary>
        ///声明一个返回值为int的委托并带两个int参数
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public delegate int MethodDelegate(int x, int y);

        //这样声明 委托就是私有的静态类
        //  private static MethodDelegate method;

        /// <summary>
        /// 创建一个返回值为int的方法带两个int参数
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        private static int Add(int x, int y)
        {
            return x + y;
        } 

调用

        public static void Main(string[] args)
        {
            #region delegate委托实现
            //实例化委托 并传方法(方法必须跟委托的返回值类型和参数类型和个数一致)   只要跟这个委托的参数和返回值一致的,所有的该方法都可以使用该委托
            MethodDelegate method = new MethodDelegate(Add);
            //然后调用委托的实例化 直接传参数(实际上调用的是add方法)
            Console.WriteLine(method(10, 20));
            #endregion

            CreateHostBuilder(args).Build().Run();
        }

执行结果 10+20=30

1.3 多播委托 一个委托想要多个方法作为参数 使用+=,-= 他会执行按顺序执行所有的方法

2 Func和Action委托的区别和简单使用

2.1 Func是一个.Net内置的泛型委托。Func是有返回值的泛型委托(必须有返回值)

Func
Func<T,TResult>
Func<T1,T2,TResult>
Func<T1,T2,T3,TResult>
Func<T1,T2,T3,T4,TResult>
展示5种形式,只是参数个数不同;第一个是无参数,但是有返回值;T1-T4表示的是参数,TResult表示返回类型
Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void

2.2 Action是无返回值的泛型委托,可以有参数

Action
Action<T1,T2>
Action<T1,T2,T3>
Action<T1,T2,T3,T4>
Action至少0个参数,至多16个参数,无返回值。T1-T4表示的是参数

2.3 附代码

先声明两个方法

        /// <summary>
        /// 声明一个带int参数并返回类型为int类型的方法
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private static int Square(int input)
        {
            return input * input;
        }
        /// <summary>
        /// 声明带一个int参数并无返回值的方法
        /// </summary>
        /// <param name="input"></param>
        private static void GetSquere(int input)
        {
            Console.WriteLine("The square of {0} is {1}.", input, input * input);
        }

委托调用

        public static void Main(string[] args)
        {
            int num = 5;
            /*  Func和Action委托的唯一区别在于Func要有返回值, Action没有返回值 */
            //注意:委托的函数的返回值和参数个数必须跟方法一样 才能等于

            //注意func的格式是<参数类型,返回参数类型>  Func<int, int>看起来是两个参数 实际上是一个返回int的类型并带一个int参数的方法
            Func<int, int> funcTest = Square;//调用的方法跟该委托声明的方法类型一致 (都是返参为int,且带一个int参数)
            Console.WriteLine("The square of {0} is {1}.", num, funcTest(num));////直接实例化的对象 Square(num)

            //无返回值 
            Action<int> actionTest = GetSquere;//调用的方法跟该委托声明的方法类型一致(都是无返回参数且只带一个int参数)
            actionTest(num);//直接实例化的对象 传参数就会直接调用GetSquere(num)


            CreateHostBuilder(args).Build().Run();
        }

输出结果

3 为什么要使用委托

委托是一个简单的类,用于指向具有特定签名的方法,它本质上是一个类型安全的函数指针。委托的目的是为了方便调用另一种方法(或方法),在完成之后,以结构化的方式。
虽然可以创建大量的代码来执行此功能

4 事件

事件是一种特殊的委托 “委托变量(参数列表)”

声明委托和事件和方法

        public delegate void DoSth(object sender, EventArgs e);
        public static event DoSth myDoSth;
        static void Print(object sender, EventArgs e)
        {
            Console.WriteLine(sender);
        }

再调用

            DoSth d = new DoSth(Print);
            object sender = 10;
            EventArgs e = new EventArgs();
            myDoSth += new DoSth(d);//+=委托(委托的实例化对象)
            myDoSth(sender, e);//执行方法
            //声明了事件myDoSth,事件的类型是DoSth这个委托
            //通过 += 为事件注册委托
            //通过DoSth委托的构造函数为事件注册委托实例
            //采用委托变量(参数列表)这种形式,让事件执行方法

推荐阅读