C#输入小于10值校验:循环与递归方法哪个更优?
实现方式选择结论
实际开发直接选do-while循环的实现就行,别用递归版本,理由很实在:
- 逻辑够直白,不管谁接手续代码,扫一眼就知道这是做输入不满足条件就重试的逻辑,没有理解成本
- 没有额外开销,也没有崩溃风险:不管用户连续输错几十次、几百次大于10的数,循环都在当前方法栈里跑,不会额外占资源,也不会出异常
- 你写的递归版本本身设计就有冗余:递归到满足条件的时候返回个空字符串,根本没被使用,属于完全没必要的设计。
这种需要重复执行、执行次数完全由外部输入决定、没有分层嵌套结构的线性逻辑,天生就适合用循环写,递归只适合用在遍历树、图这类本身有递归结构、深度可控的场景,硬套在输入重试这种地方纯属于给自己挖坑。
关于“递归造成内存泄漏”的说法澄清
这个说法属于概念传歪了,你写的这个递归版本不会造成内存泄漏,但有很高的栈溢出崩溃风险:
- 先明确概念:内存泄漏指的是程序申请的内存因为逻辑bug没法被垃圾回收器回收,内存占用持续上涨最后把内存耗光。你这段递归代码里没有占着非托管资源不释放、也没有长期持有无用对象引用的问题,托管内存都会被正常回收,不存在内存泄漏的问题。
- 真正的问题是栈溢出:C#默认给每个线程分配的栈空间只有几MB,每次调用
Value()方法都会往调用栈里压一个新的栈帧。只要用户连续输错足够多次(比如连续输个大几十次大于10的数),栈深度就会顶到阈值,直接抛出StackOverflowException——这个异常是没法被捕获的,一抛程序直接崩。 - 别指望尾递归优化救这个写法:很多人觉得递归写对了能被优化成循环不占栈,但你现在这个写法根本不满足尾递归的要求,JIT编译器不会给你做优化,栈帧该压还是压,崩是迟早的事。
提问对应的示例代码
class Program { static void Main(string[] args) { int x; do { Console.WriteLine("Please Enther a value less than 10."); x = int.Parse(Console.ReadLine()); } while (x > 10); //Uncomment the bellow method and comment previous to test the Recursive method //Value(); } static string Value() { Console.WriteLine("Please Enther a value less than 10."); return int.Parse(Console.ReadLine()) > 9 ? Value() : ""; } }
内容的提问来源于stack exchange,提问作者Javad-M
相关产品推荐
相关产品推荐

