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并没有改变。

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

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

  • 相关阅读:
    keras系列︱迁移学习:利用InceptionV3进行fine-tuning及预测、完美案例(五)
    keras系列︱人脸表情分类与识别:opencv人脸检测+Keras情绪分类(四)
    keras系列︱图像多分类训练与利用bottleneck features进行微调(三)
    keras系列︱Application中五款已训练模型、VGG16框架(Sequential式、Model式)解读(二)
    将C++资源文件读取出来
    windows驱动程序中的预处理含义
    win10网上邻居看不到别的共享电脑怎么样办
    #pragma alloc_text 与 ALLOC_PRAGMA
    IoAllocateMdl,MmProbeAndLockPages的用法
    Composer三步曲:安装、使用、发布
  • 原文地址:https://www.cnblogs.com/rui1236/p/7091721.html
Copyright © 2011-2022 走看看