zoukankan      html  css  js  c++  java
  • 容易忽略的递归当中的return

    先描述问题。

    最近项目有个需求,数据入库失败后延时一定时间然后重新入库;当失败达到一定次数后就不再进行入库,因为项目简单,也不需要异步处理。所以看到这个问题很容易想到用递归去实现。

    我最开始的代码example:

    /// <summary>
            /// 错误次数
            /// </summary>
            static int errorCount = 0;
    
            /// <summary>
            /// 测试递归代码
            /// </summary>
            /// <returns></returns>
            static int TestFun()
            {
                try
                {
                    Console.WriteLine("enter fun ");
                    int a = 0;
                    int n = 3 / a;
                }
                catch (Exception ex)
                {
                    if (errorCount >= 3)
                    {
                        Console.WriteLine("number of error==3 bye");
                        return 0;
                    }
                    errorCount++;
                    Thread.Sleep(1000);
                    TestFun();
                }
                return 1;
            }

    这个代码我想很多人第一眼看到就很容易想到这个TestFun方法一定返回0,因为除数不能为0 所以一直报错 直到错误大于3 return了。

    实际结果应该是1 原因很简单,catch里的return 是递归这个方法中的return。这个时候TestFun并没有全部退出,只是退出了递归的那一层而已。递归退出完了 也就是catch语句块执行完毕后,会继续执行return1。

    这个问题本身并不难理解,只是我们都有个固有的思维 方法中return了 就不会执行下面代码了。然后就会忽略下面的递归调用。

    说到固有思维我再举个例子还是这个问题。

     /// <summary>
            /// 测试递归代码
            /// </summary>
            /// <returns></returns>
            static int TestFun()
            {
                int result = 1;
                try
                {
                    Console.WriteLine("enter fun ");
                    int a = 0;
                    int n = 3 / a;
                }
                catch (Exception ex)
                {
                    if (errorCount >= 3)
                    {
                        Console.WriteLine("number of error==3 bye");
                        result = 0;
                        return 0;
                    }
                    errorCount++;
                    Thread.Sleep(1000);
                    TestFun();
                }
                return result;
            }

    这个代码 不直接return具体值了,而是将值保存到一个变量里。第一眼看这个代码心想这次应该要返回0了吧,出错后 result已经被赋值0了 这下最后面的return 应该返回1了。

    正确结果其实也是返回1。说到底还是因为递归,我们catch 里的result=0 其实是针对当前递归这个方法里面的result。因为我们先递归后改变值的;

    我们可以这样去想象:当我一次递归时我们方法是TestFun1 第二次是TestFun2 第三次是 TestFun3  里面的代码还是一样的。所以我catch里面的result其实是对应我TestFun3 里的result。直到我们退出递归回到最初的方法里面即TestFun 时它的result还是1并没有改变。

    造成我们直觉上的错误其实就是我一开始说的那种固有思维,代码中变量被赋值后,下面代码没有再操作这个值 那么这个值应该是被修改后的值;当然这种思维在没有递归代码当中肯定是正确的。

    当我们递归写的少的情况很容易造成以上那种直觉上的错误判断。

  • 相关阅读:
    Unity3D性能优化之资源导入标准和属性设置篇
    博客主题-Next风格
    Pytorch 搭建 LeNet-5 网络
    CIFAR数据集解读
    Mnist数据集解读
    博客主题——cnbook
    博客主题——element v2
    更换清华镜像源
    图像插值技术——双线性插值法
    PASCAL VOC2012数据集解读
  • 原文地址:https://www.cnblogs.com/rui1236/p/7091721.html
Copyright © 2011-2022 走看看