先描述問題。

最近項目有個需求,數(shù)據(jù)入庫失敗后延時一定時間然后重新入庫;當(dāng)失敗達到一定次數(shù)后就不再進行入庫,因為項目簡單,也不需要異步處理。所以看到這個問題很容易想到用遞歸去實現(xiàn)。

我最開始的代碼example:

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機開發(fā)培訓(xùn),手機維修培訓(xùn),手機軟件培訓(xùn)

/// <summary>
        /// 錯誤次數(shù)        /// </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;
        }

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機開發(fā)培訓(xùn),手機維修培訓(xùn),手機軟件培訓(xùn)

 

這個代碼我想很多人第一眼看到就很容易想到這個TestFun方法一定返回0,因為除數(shù)不能為0 所以一直報錯 直到錯誤大于3 return了。

實際結(jié)果應(yīng)該是1 原因很簡單,catch里的return 是遞歸這個方法中的return。這個時候TestFun并沒有全部退出,只是退出了遞歸的那一層而已。遞歸退出完了 也就是catch語句塊執(zhí)行完畢后,會繼續(xù)執(zhí)行return1。

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機開發(fā)培訓(xùn),手機維修培訓(xùn),手機軟件培訓(xùn)

 

這個問題本身并不難理解,只是我們都有個固有的思維 方法中return了 就不會執(zhí)行下面代碼了。然后就會忽略下面的遞歸調(diào)用。

 

說到固有思維我再舉個例子還是這個問題。

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機開發(fā)培訓(xùn),手機維修培訓(xùn),手機軟件培訓(xùn)

 /// <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;
        }

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機開發(fā)培訓(xùn),手機維修培訓(xùn),手機軟件培訓(xùn)

這個代碼 不直接return具體值了,而是將值保存到一個變量里。第一眼看這個代碼心想這次應(yīng)該要返回0了吧,出錯后 result已經(jīng)被賦值0了 這下最后面的return 應(yīng)該返回1了。

移動開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機開發(fā)培訓(xùn),手機維修培訓(xùn),手機軟件培訓(xùn)

 

正確結(jié)果其實也是返回1。說到底還是因為遞歸,我們catch 里的result=0 其實是針對當(dāng)前遞歸這個方法里面的result。因為我們先遞歸后改變值的;

我們可以這樣去想象:當(dāng)我一次遞歸時我們方法是TestFun1 第二次是TestFun2 第三次是 TestFun3  里面的代碼還是一樣的。所以我catch里面的result其實是對應(yīng)我TestFun3 里的result。直到我們退出遞歸回到最初的方法里面即TestFun 時它的result還是1并沒有改變。

造成我們直覺上的錯誤其實就是我一開始說的那種固有思維,代碼中變量被賦值后,下面代碼沒有再操作這個值 那么這個值應(yīng)該是被修改后的值;當(dāng)然這種思維在沒有遞歸代碼當(dāng)中肯定是正確的。

當(dāng)我們遞歸寫的少的情況很容易造成以上那種直覺上的錯誤判斷。

http://www.cnblogs.com/rui1236/p/7091721.html