C#进阶:委托和事件

更多
2020年04月09日 09点05分 作者:叶飞 修改

引子

看看这个例子,能不能:想进行加法运算的时候就加法,想乘法的时候就乘法?

        static void AICaculate(int a, int b)
        {
            Console.WriteLine("I'm AI caculator, let me try:");
            Add(a, b);
            //Multiple(a, b);
        }

        static void Add(int a, int b)
        {
            Console.WriteLine($"it's so easy, {a}+{b}={a + b}");
        }

        static void Multiple(int a, int b)
        {
            Console.WriteLine($"I can I can, {a}*{b}={a * b}");
        }

思路:通过AICaculate()的参数进行控制,

        static void AICaculate(int a, int b, string opt)
        {
            Console.WriteLine("I'm AI caculator, let me try:");
            if (opt == "Add")  //add
            {
                Add(a, b);
            }
            else
            {
                Multiple(a, b);
            }
        }

程序员应该对使用string类型进行判断比较保持警惕:

    enum Opt    //应当引入enum
    {
        Add,
        Multiple,
        //Minus
    }


然后,使用switch...case:

            switch (opt)
            {
                case Opt.Add:
                    Add(a, b);
                    break;
                case Opt.Multiple:
                    Multiple(a, b);
                    break;
                default:
                    //复习:为什么要抛出异常
                    throw new ArgumentException("");
            }
一个可行的办法,是将方法本身(而不是方法的结果)作为参数传递过来:
        public static void Main(string[] args)
        {
            AICaculate(Add,      /* 将方法直接传入 */
                3, 5);
        }

        static void AICaculate(Action<int, int> calculate, /*这个参数是什么鬼?*/
            int a, int b)
        {
            Console.WriteLine("I'm AI caculator, let me try:");
            calculate(a, b);
        }


委托(delegate)

F12查看 Action<int, int> 的定义,我们发现:

public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
注意关键字delegate(委托),而不是通常的class或struct。

什么是委托?

  • 委托是一种(特殊的)类型
  • 代表的是方法(的引用),所以需要指定参数和返回值
        //像声明一个类一样声明一个委托
        //但定义了这个委托的返回void类型,接受两个int类型的参数
        delegate void Calculate(int a, int b);
  • 委托类型的变量可以像方法一样使用
                //把方法(不是方法的返回值)直接赋值给一个Calculate委托变量
                Calculate ai = Add;
                //类似于调用Add()方法一样调用delegateAdd
                ai(3, 7);

另外,委托类型的变量可以和普通变量一样的:

  • 被赋值
  • 作为方法参数传递
  • 作为方法返回值


Func和Action

而且,为了便于Lambda表达式的传递,.NET为我们预置了两种委托:

  • Func:有返回值的方法。使用泛型参数依次表示方法参数,最后一个表示方法返回值
  • Action:没有返回值的方法。使用泛型参数依次表示方法参数

Func和Action为我们提供了最多16个参数,怎么都够用了!^_^

@想一想@:如果说16个参数还不够怎么办?

而且这两种委托都是泛型的,所以我们基本上都不再自己声明委托了。

public delegate TResult Func<in T, out TResult>(T arg);
public delegate void Action<in T>(T obj);



事件(event)

委托是事件的基础,事件又对委托进行了封装……

在Winform和以前的WebForm中,事件被大量使用,是必须掌握的知识(但MVC不是事件驱动的),一个完整的事件流程包括:

    public class Button
    {
        //定义事件,用于发布
        public event EventHandler OnClick;    //注意:EventHnadler是一个委托
        public void click()
        {
            if (OnClick != null)
            {
                OnClick(this, new EventArgs());
            }
        }
    }
            //实例化一个发布了OnClick事件的button
            Button btn = new Button();
            //事件被btn_click订阅,即:当这个btn被click时调用btn_click()方法
            btn.OnClick += btn_click;
        private static void btn_click(object sender, EventArgs e)
        {
            Console.WriteLine("点我干啥呢?");
        }
            //事件被触发
            btn.click();

注意:event和delegate都可以被多次订阅(+=)/退订(-=),演示:略

C# 委托 事件
赞: 3 踩: 0

打赏
已收到打赏的 帮帮币

你的 打赏 非常重要!
为了保证文章的质量,每一篇文章的发布,都已经消耗了作者 1 枚 帮帮币
没有“帮帮币”,作者无法发布新的文章。

全系列阅读
评论 / 0

后台开发


ADO和EF

如何通过C#进行数据库的读取,包含ADO.NET和Entity Framework相关知识……

其他:WebForm和WebApi

其他ASP.NET框架,如WebForm、WebApi……

RazorPages(Core)

微软推荐的、最新的、基于Razor页面和.NET core的新一代Web项目开发技术,包括Razor Tag Helper、Model绑定和Validation、Session/Cookie、内置依赖注入等……

MVC(Framework)

过去两年间最流行的、基于.NET Framework和MVC模式的ASP.NET MVC框架,主要用于讲解安全、性能、架构和各种实战功能演示……

C#语法

从入门的变量赋值、分支循环、到面向对象,以及更先进的语言特性,如:泛型、Lambda、Linq、异步方法等…………

Java语法

面向过程的变量赋值、分支循环和函数封装;面向对象的封装、继承和多态;以及更高阶的常用类库(集合/IO/多线程……)、lambda等

Java Web开发

SpringMVC

分层架构和综合实战

全部
关键字



帮助

反馈