为什么要使用迭代而不是尾递归?

什么是设计气味,递归的不良做法? 一旦我看到resharper暗示改进,我就快速浏览了谷歌。 看到关于将尾递归重新分解为迭代并将其称为设计气味的众多评论。

public static void DebugOutput2(Exception ex) { if (ex == null) { return; } Debug.WriteLine(ex.Message); if (ex.InnerException != null) { DebugOutput2(ex.InnerException); } } // WAS REFACTORED TO public static void DebugOutput(Exception ex) { if (ex == null) { return; } while (true) { Debug.WriteLine(ex.Message); if (ex.InnerException != null) { ex = ex.InnerException; continue; } break; } } 

编辑:获得C#编译器处理评论。 看起来它现在是递归的
目标.net 4.5。 C#5.0

用于尾递归版本的ILDASM输出:显示递归调用而不是迭代

 .method public hidebysig static void DebugOutput(class [mscorlib]System.Exception ex) cil managed { // Code size 54 (0x36) .maxstack 2 .locals init ([0] bool CS$4$0000) IL_0000: nop IL_0001: ldarg.0 IL_0002: ldnull IL_0003: ceq IL_0005: ldc.i4.0 IL_0006: ceq IL_0008: stloc.0 IL_0009: ldloc.0 IL_000a: brtrue.s IL_000e IL_000c: br.s IL_0035 IL_000e: ldarg.0 IL_000f: callvirt instance string [mscorlib]System.Exception::get_Message() IL_0014: call void [System]System.Diagnostics.Debug::WriteLine(string) IL_0019: nop IL_001a: ldarg.0 IL_001b: callvirt instance class [mscorlib]System.Exception [mscorlib]System.Exception::get_InnerException() IL_0020: ldnull IL_0021: ceq IL_0023: stloc.0 IL_0024: ldloc.0 IL_0025: brtrue.s IL_0035 IL_0027: nop IL_0028: ldarg.0 IL_0029: callvirt instance class [mscorlib]System.Exception [mscorlib]System.Exception::get_InnerException() IL_002e: call void ca1.Program::DebugOutput(class [mscorlib]System.Exception) IL_0033: nop IL_0034: nop IL_0035: ret } // end of method Program::DebugOutput 

因为人们错误地关注微优化而不是清晰可读的代码。

递归为每个级别(您处理的每个对象)进行附加(递归)函数调用,这也意味着堆栈分配。

通常,迭代更好,因为它不会进行额外的调用/分配。

当然,如果有许多对象需要处理,那么差异是可见的,我想在你的例子中并非如此。 所以对你而言,这不是一个问题,我想这是为了教会你一般的更好的练习。