C#回调函数的简单讲解与应用例子,简单例子明白意义所在

原文链接:https://blog.csdn.net/sajiazaici/article/details/78702144

总结:

1.就是可以封装一个类,把一直的功能写好,回调函数可以单独修改内容,然后后造成原来程序函数的功能更新,这应该就是回调函数的好处。

2.或者说是可以将一个对象的函数当成参数进行使用。

 

C#回调函数的简单讲解与应用例子(最简单讲解,大神绕道)
原创董董在这 最后发布于2017-12-03 17:21:48 阅读数 17004  收藏
展开
本博客一直以来的宗旨就是:用最简单的方式讲清楚不复杂的问题。

因为本人也很菜所以也没法讲太复杂HHHHHH......

所以如果哪天某个大神看到了觉得讲的有问题欢迎指出。

话不多说进入正题。。

——————————————————————————————————————

这篇文章的目的就是讲清楚C#回调函数是什么,以及什么时候使用。

直接拿例子来讲算了- -

 

using System;
 
namespace CallBackTest
{
    class Program //用户层,执行输入等操作
    {
        static void Main(string[] args)
        {
            
            CalculateClass cc = new CalculateClass();
            FunctionClass fc = new FunctionClass();
 
            int result1 = cc.PrintAndCalculate(2, 3, fc.GetSum);
            Console.WriteLine("调用了开发人员的加法函数,处理后返回结果:" + result1);
 
            int result2 = cc.PrintAndCalculate(2, 3, fc.GetMulti);
            Console.WriteLine("调用了开发人员的乘法函数,处理后返回结果:" + result2);
 
            Console.ReadKey();
        }
 
        
    }
 
    class FunctionClass   //开发层处理,开发人员编写具体的计算方法
    {
        public int GetSum(int a, int b)
        {
            return (a + b);
        }
        public int GetMulti(int a, int b)
        {
            return (a * b);
        }
    }
 
    #region 实际开发中,下面这个类会封装起来,只提供函数接口。相当于系统底层
    class CalculateClass 
    {
        public delegate int SomeCalculateWay(int num1, int num2);
 
        //将传入参数在系统底层进行某种处理,具体计算方法由开发者开发,函数仅提供执行计算方法后的返回值
        public int PrintAndCalculate(int num1 , int num2 , SomeCalculateWay cal) 
        {
            Console.WriteLine("系统底层处理:" + num1);
            Console.WriteLine("系统底层处理:" + num2);
            return cal(num1, num2);//调用传入函数的一个引用   
        }
        //可以封装更多的业务逻辑方法   
        
    }
    #endregion
 
}
直接复制进控制台项目即可运行。

 

运行结果:

 

 

 

感觉例子还是比较直白的。例子能看懂就不用看下面的了。

 

下面详细解释一下(包含一些关于封装的意义):

1、中间的FunctionClass中的GetSum()和GetMulti()两个函数称为回调函数。可以看到整个程序中并没有哪个地方通过类似GetSum(1,2)这种形式调用了该函数,只有将其当作另一个函数的参数来进行调用。如cc.PrintAndCalculate(2, 3, fc.GetSum)。

下面是百度百科的定义:

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

 

简单来说,就是 public delegate int SomeCalculateWay(int num1, int num2) 这行代码,把 SomeCalculateWay 这几个字符定义成一种类型,什么类型呢?-> 带了两个int参数的函数类型。而PrintAndCalculate()函数的第三个参数是这种类型,GetSum(int,int)也是这种类型,所以GetSum这个函数可以被当做参数传入,并且在打印完两个数字后执行,被称为回调函数。

自此代码部分解释完毕

 

有的同学可能会问了,那为什么不直接写int result1 = GetSum(1,2)呢?岂不是更方便?用这个回调函数意义在哪呢?

这就涉及到封装和实际开发的问题了 ↓

________________________________________________________

我们假想一下这个情况:

我们的项目是个核武器控制器,假设并没有涉及到回调函数。当用户输入1,2并且执行GetSum(1,2)的时候,这个工程会把1,2写进核武器的发射系数里,比如方向方位等,然后GetSum求得发射距离,之后进行发射。

看起来也很完美?没什么瑕疵?

 

不,有没有想过万一哪天操作失误了呢。万一哪天某个人输入错了,把-1,-2输入进去了,现在倒好,本来要打到外面去的导弹打到自己家了,这个损失就是不可估量的了。

 

你可能又会说了,那让程序员在客户端(用户端)判断一下呗,比如加一句 if(a>0 && b>0) getsum(a,b);

那你有没想过,万一哪天这个程序员的代码写错了一行呢?或者派了一个像我一样很菜的实习生过来写代码?岂不是又要把导弹打到自己家了吗hhhhhhhh。所以,在实际大型应用中,“把参数写进核武器” 这个操作的代码并不是所有人都能接触到的,只有项目里最核心的工程师经过反复测验才能应用上去的,而且要对这些参数甚至是结果进行必要的判断,并且如果要修改代码也是会经过慎重考量的,因为你一改,相当于整个项目底层都进行了改变,所有调用你函数的人执行效果也都会发生改变。

以上就是封装的意义。(当然封装还有其他意义这里就不赘述了)

______________________________________________________________________

2、在实际开发中,CalculateClass这个类会被封装起来,比如提供一个dll文件给你,你通过引用dll来调用里面的参数或者函数。一般项目里的大佬/主程都会把这些底层的东西打包进dll,防止误操作使得系统崩溃,也让外界不能轻易访问底层的东西。

在这个类中,public delegate int SomeCalculateWay(int num1, int num2); 这一语句声明了一个委托,后面定义的SomeCalculateWay cal就代表着cal是一个带有两个int参数的函数。关于委托的例子和应用这里也不多讲了,能理解就好。

 

3、在用户层的main函数里,用户可以通过输入参数2,3,然后获取一个开发人员的方法比如getsum,然后把这些作为参数,调用底层的函数,再得到想要的效果。这样子不管是用户还是开发人员误操作了,最后都会被底层的函数给判断出来,从而不会执行错误的结果而造成损失。

 

4、当然封装是回调函数的一种用法,还有一种用法就是在有网络延迟的情况下,可以告诉外界某段代码已经在一定延迟后执行完毕,此时回调函数就作为执行后接下来要进行的操作,更详细的用法后续再进行说明。

 

说了这么多,感觉讲的还是挺清楚的,适合新手看看。。

如果哪里有错误也希望大家指出,谢谢。。
 

上一篇:用javascript写第一个函数


下一篇:leetcode 111 二叉树的最小深度