什么是回调函数

回调函数就是允许用户把需要调用的函数的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法,简而言之就是一个被作为参数传递的函数,回调函数的作用是对特定的事件或条件进行响应。(引用自百度百科)

情景模拟

一个公司的老板需要知道员工是否完成了任务,所以他要求员工如果完成了任务需要给他提交报告。(这个员工就是作者,完成了任务却得不到一个赞😭)

情景分析

回调函数定义者:老板

响应函数定义者:员工

回调函数:提交报告

触发回调函数的条件:员工完成任务

解决思路

首先,我们得有一个Boss类和Employee类分别代表老板和员工,而员工要向老板提交报告,肯定需要知道老板办公室的地址,所以再定义一个IBossOffice接口,接口下声明提交报告这个事件Report,然后我们的老板需要实现这个接口,这样我们的员工就可以通过接口来向老板提交报告了,那么员工需要具备哪些属性和行为呢?首先员工得知道老板的办公室地址officeAddress,然后得有开始工作的行为StartTask,还得有一个完成任务的行为FinishTask。为了使得我们的代码更贴近情景模拟,我特意给员工添加了一个名字属性employeeName,以及提交报告时告知老板员工的名字和计时器。

思路图

c grpc 回调函数 回调函数c#_参数传递

代码实现

class CallBackTest
    {
        static void Main(string[] args)
        {
            //得有一个Boss
            Boss boss = new Boss();
            //根据Boss得知Boss办公室的地址
            IBossOffice officeAddress = boss as IBossOffice;
            //还得有一个员工,这个员工需要知道Boss办公室的地址和自己的名字
            Employee employee = new Employee(officeAddress, "小王");
            //员工开始工作
            employee.StartTask();
        }
    }

    class Boss : IBossOffice
    {
        //回调函数
        public void Report(Employee e)
        {
            Console.WriteLine("员工" + e.employeeName + "完成任务来提交报告啦.");
        }
    }

    public interface IBossOffice
    {
        public void Report(Employee e);
    }

    public class Employee
    {
        //这里的officeAddress就是Boss办公室的地址
        private IBossOffice officeAddress;
        private Timer timer;
        public string employeeName { get; }

        //员工要知道Boss办公室地址才能完成提交报告的任务
        public Employee(IBossOffice officeAddress, string employeeName)
        {
            this.officeAddress = officeAddress;
            //下面这是一个计时器,与当前要说的回调内容无关
            timer = new Timer();
            timer.AutoReset = false;
            timer.Interval = 5000;
            timer.Elapsed += FinishTask;
            //员工姓名
            this.employeeName = employeeName;
        }

        //员工开始做任务
        public void StartTask()
        {
            Console.WriteLine("员工" + employeeName + "开始工作了.");
            timer.Start();
        }

        //响应函数
        //员工完成任务去Boss办公室提交报告
        private void FinishTask(object sender, ElapsedEventArgs e)
        {
            Console.WriteLine("员工" + employeeName + "完成任务了.");
            officeAddress.Report(this);
        }
    }

代码解说

结合回调函数的定义,我们这里的回调函数实际上就是IBossOffice下的Report函数,我们在定义员工的时候,把IBossOffice作为一个参数传递给了员工,所以这是回调函数的第一个特征作为被传递的参数,员工开始任务StartTask,当任务完成时,在FinishTask中有一段代码officeAddress.Report(this)就是我们在响应函数中调用回调函数,这就是回调函数的第二个特征它会对特定的事件或条件进行响应。为什么Report函数是回调函数呢?首先定义Report的是Boss,也就是老板要求员工完成任务要提交报告,而执行Report的是员工,也就是说什么时候提交报告是员工来决定的,员工完成了任务才提交报告。如果我们不采用回调函数,我们完全可以在Main函数中来决定什么时候Report,那么这样老板和员工之间的沟通相当于就得通过秘书,这就会导致一个问题,员工和老板的沟通可能无法及时传达给对方,因为秘书可能因为事情太多而忘记把员工的任务报告提交给老板,虽然实际生活中老板会让秘书来传达工作要求,但是代码中我们为了提高编程效率就让老板和员工直接进行沟通,而回调函数就是作为老板和员工之间进行沟通的接口,老板把IBossOffice这个接口发送给员工,员工就能够通过IBossOffice来实现与老板的沟通,即Report。