C#自定义LIFO类Reset函数赋值错误且foreach遍历失效如何解决
问题产生原因
- 打印逻辑错误:Program.cs的foreach循环中,你打印的是LIFO类的实例
l,而非遍历得到的元素item,所以输出的是TestApp.LIFO的类型名,而非预期的字符元素,这也是你第一次直接返回数组枚举器时结果不符合预期的直接原因。 - 枚举器实现不符合C#规范:
- C#的
foreach语法不会自动调用枚举器的Reset方法,该方法仅为COM互操作预留,绝大多数场景下不会被运行时调用。你的代码中枚举状态字段_i默认初始值为0,第一次执行MoveNext时会直接减为-1,返回false直接结束遍历,因此无任何输出。 - 你将集合类本身同时实现了
IEnumerable和IEnumerator,会导致枚举状态和集合实例绑定,嵌套遍历、多线程遍历时会出现状态冲突,属于设计错误。
- C#的
可行解决方案
推荐用C#迭代器语法实现遍历,无需手动维护枚举状态,代码简洁且符合规范:
步骤1:删除LIFO类中手动实现的枚举器相关代码
移除_i字段、MoveNext、Reset、Current成员,仅保留GetEnumerator方法,用yield return返回倒序的栈元素(符合LIFO遍历逻辑)。
步骤2:修复打印逻辑
将Program.cs中打印对象改为遍历得到的item。
步骤3:修复隐藏的构造函数Bug
传入数组的构造函数需要将栈指针_index初始化为数组长度,否则原有数组的元素无法被识别。
修正后的LIFO类代码
using System; using System.Collections; namespace TestApp { internal class LIFO : IEnumerable { public LIFO(int size) { _arr = new char[size]; _index = 0; } public LIFO(char[] arr) { _arr = arr.Clone() as char[]; // 修复构造函数指针初始化错误 _index = arr.Length; } public char Peek() => _index == 0 ? '\0' : _arr[_index - 1]; public bool Add(char c) { if (_index == _arr.Length) return false; _arr[_index] = c; ++_index; return true; } public void Pop() { if (_index == 0) return; _arr[--_index] = '\0'; } public IEnumerator GetEnumerator() { // 倒序返回已写入的元素,符合LIFO遍历逻辑 for (int i = _index - 1; i >= 0; i--) { yield return _arr[i]; } } private int _index; private readonly char[] _arr; } }
修正后的Program.cs代码
using System; namespace TestApp { internal static class Program { private static void Main() { LIFO l = new(17); l.Add('k'); l.Add('h'); l.Add('c'); foreach (var item in l) // 修复打印对象错误 Console.WriteLine(item); } } }
运行后输出结果符合LIFO后进先出的预期:
c h k
内容的提问来源于stack exchange,提问作者Scott
相关产品推荐
相关产品推荐

