容易忽略的递归当中的return
先描述问题。
最近项目有个需求,数据入库失败后延时一定时间然后重新入库;当失败达到一定次数后就不再进行入库,因为项目简单,也不需要异步处理。所以看到这个问题很容易想到用递归去实现。
我最开始的代码example:
/// <summary>
/// 错误次数
/// </summary>
static int errorCount = ; /// <summary>
/// 测试递归代码
/// </summary>
/// <returns></returns>
static int TestFun()
{
try
{
Console.WriteLine("enter fun ");
int a = ;
int n = / a;
}
catch (Exception ex)
{
if (errorCount >= )
{
Console.WriteLine("number of error==3 bye");
return ;
}
errorCount++;
Thread.Sleep();
TestFun();
}
return ;
}
这个代码我想很多人第一眼看到就很容易想到这个TestFun方法一定返回0,因为除数不能为0 所以一直报错 直到错误大于3 return了。
实际结果应该是1 原因很简单,catch里的return 是递归这个方法中的return。这个时候TestFun并没有全部退出,只是退出了递归的那一层而已。递归退出完了 也就是catch语句块执行完毕后,会继续执行return1。

这个问题本身并不难理解,只是我们都有个固有的思维 方法中return了 就不会执行下面代码了。然后就会忽略下面的递归调用。
说到固有思维我再举个例子还是这个问题。
/// <summary>
/// 测试递归代码
/// </summary>
/// <returns></returns>
static int TestFun()
{
int result = ;
try
{
Console.WriteLine("enter fun ");
int a = ;
int n = / a;
}
catch (Exception ex)
{
if (errorCount >= )
{
Console.WriteLine("number of error==3 bye");
result = ;
return ;
}
errorCount++;
Thread.Sleep();
TestFun();
}
return result;
}
这个代码 不直接return具体值了,而是将值保存到一个变量里。第一眼看这个代码心想这次应该要返回0了吧,出错后 result已经被赋值0了 这下最后面的return 应该返回1了。

正确结果其实也是返回1。说到底还是因为递归,我们catch 里的result=0 其实是针对当前递归这个方法里面的result。因为我们先递归后改变值的;
我们可以这样去想象:当我一次递归时我们方法是TestFun1 第二次是TestFun2 第三次是 TestFun3 里面的代码还是一样的。所以我catch里面的result其实是对应我TestFun3 里的result。直到我们退出递归回到最初的方法里面即TestFun 时它的result还是1并没有改变。
造成我们直觉上的错误其实就是我一开始说的那种固有思维,代码中变量被赋值后,下面代码没有再操作这个值 那么这个值应该是被修改后的值;当然这种思维在没有递归代码当中肯定是正确的。
当我们递归写的少的情况很容易造成以上那种直觉上的错误判断。
容易忽略的递归当中的return的更多相关文章
- python递归中的return"陷阱"
在做一道练习题(参照下篇博文<在当前目录下递归的查找包含指定字符串的文件>)的时候,发现函数中的return的值竟然是None,百思不得其解,尝试化繁为简,用以下的简单的代码验证了一下 问 ...
- 经常犯的错误之递归写不全return
在写递归函数的时候,只在最后一层写return,中间的过程没有return,导致结果的丢失. 举个例子 LL query(LL i, LL k) { if (sum[i] < k) { ; } ...
- python学习笔记之装饰器、递归、算法(第四天)
参考老师的博客: 金角:http://www.cnblogs.com/alex3714/articles/5161349.html 银角:http://www.cnblogs.com/wupeiqi/ ...
- iOS 阶段学习第七天笔记(函数、递归)
iOS学习(C语言)知识点整理笔记 一.函数 1)概念:具有特定功能的代码块的封装 2)函数的定义: 函数类型+函数名(形参列表) 函数类型 函数名(形参类型1 形参名1,形参类型2 形参名2 ...
- Python的递归
递归 是指函数/过程/子程序在运行过程序中直接或间接调用自身而产生的重入现象.在计算机编程里,递归指的是一个过程:函数不断引用自身,直到引用的对象已知.使用递归解决问题,思路清晰,代码少.但是在主流高 ...
- 递归、尾递归和使用Stream延迟计算优化尾递归
我们在学数据结构的时候必然会接触栈(Stack),而栈有一个重要的应用是在程序设计语言中实现递归.递归用途十分广泛,比如我们常见的阶乘,如下代码: 1234 public static int (in ...
- 傻瓜式理解递归之php递归
写程序这么久了,有时候别人会问道一些算法比如排序啊,递归啊,总是不知道该怎么去说,今天就来整理一下,让更多的人去傻瓜式的理解递归.递归在网络上有很多定义,但有这么一句话听的最多:递归就是自己调用自己! ...
- MyBatis一级缓存引起的无穷递归
MyBatis一级缓存引起的无穷递归 引言: 最近在项目中参与了一个领取优惠劵的活动,当多个用户领取同一张优惠劵的时候,使用了数据库锁控制并发,起初的设想是:如果多个人同时领一张劵,第一个到达的人领取 ...
- 算法笔记_017:递归执行顺序的探讨(Java)
目录 1 问题描述 2 解决方案 2.1 问题化简 2.2 定位输出测试 2.3 回顾总结 1 问题描述 最近两天在思考如何使用蛮力法解决旅行商问题(此问题,说白了就是如何求解n个不同字母的所有不同排 ...
随机推荐
- Docker - 定制镜像
Dockerfile Docker Hub拥有大量高质的官方镜像:可直接使用的服务类镜像.语言应用镜像.基础操作系统镜像等,满足绝大部分需求. 此外,可以通过定制镜像的方式来满足实际使用中的特定需求. ...
- percona-xtrabackup安装
二进制包安装(推荐安装方式,不用安装依赖包,非常方便): 1.下载安二进制包: wget https://www.percona.com/downloads/XtraBackup/Perco ...
- Java 7之基础 - 强引用、弱引用、软引用、虚引用
1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.如下: Object o=new Object(); // 强引用 当内 ...
- 1.centOS安装Mysql
上个星期研究了一个星期的Mysql,从今天起把学到的东西整理一下. ---------------------------------------------- mysql安装本人亲试过两种安装方式, ...
- MyBatis之TypeHandler
在大学写web应用的时候经常会遇到这么个问题,当我要插入一条数据,某个数据是Date类型,数据库中却是VARCHAR类型,这个时候可能会傻乎乎的先把这个数据自己手动转换成String类型再插入到数据库 ...
- 在 eclipse 中将 web 项目部署到 tomcat 服务器上
1.在 eclipse 中,选择 Window--->Preferences--->Server--->Runtime Environments,选择 Add 按钮 2.在弹出的对话 ...
- /proc/kcore失效,调试其文件系统相关模块,使重新正常工作
为分析内核,在有限的机器上用虚拟机装了CentOS.6.9.i386.minimal,重新编译了3.19.8内核并克隆.当使用/proc/kcore进行内核动态映像调试时,发现与kgdb远程调试端读到 ...
- tomcat产生大量TIME_WAIT连接
http://blog.csdn.net/jiangguilong2000/article/details/12523771
- LVM学习
LVM Logical Volume Manager Volume management creates a layer of abstraction over physical storage, a ...
- Creating beautiful charts in chinese with ggplot2
Before we start My chinese skills are poor and biased. I did learn during my internship and I contin ...