如何实现可表示int、null或自身数组的C#类?
设计问题:实现支持int/null/自身数组的类
需求说明
创建MyIntOrArray类,其实例需支持三种形态:int值、null、该类的数组。调用打印方法时需满足:
- 若为int值,打印对应数字
- 若为null,无任何操作
- 若为数组,遍历并打印内部元素
补充要求:对于结构[[1,2,3], null, 4, 5, [6,null,7]](所有元素包括主数组均为MyIntOrArray类型),调用打印方法7次需依次输出"1""2""3""4""5""6""7"。核心关注类的实现结构,而非打印功能细节。
尝试实现代码
public class MyIntOrArray { public int? Value { get; set; } public MyIntOrArray[] Values { get; set; } private bool AmIArray { get; set; } private int InnerIndex { get; set; } public MyIntOrArray(int? value) { Value = value; AmIArray = false; } public MyIntOrArray(int size, bool isArray) { Values = new MyIntOrArray[size]; AmIArray = true; } public bool Print() { if(AmIArray) { if (InnerIndex < Values.Length) { if (Values[InnerIndex].Print()) InnerIndex += 1; return InnerIndex >= Values.Length ? true : false; } } else if(Value != null) { Console.WriteLine(Value.ToString()); } return true; } }
优雅实现方案
方案一:基于继承与多态的实现
通过抽象基类+子类的方式,明确区分三种形态,符合单一职责原则:
// 抽象基类,定义统一行为 public abstract class MyIntOrArray { public abstract bool Print(); } // 表示int值的子类 public class MyInt : MyIntOrArray { public int Value { get; } public MyInt(int value) => Value = value; public override bool Print() { Console.WriteLine(Value.ToString()); return true; } } // 表示null的单例子类 public class MyNull : MyIntOrArray { public static readonly MyNull Instance = new MyNull(); private MyNull() { } public override bool Print() => true; } // 表示数组的子类 public class MyIntArray : MyIntOrArray { private readonly MyIntOrArray[] _elements; private int _currentIndex = 0; public MyIntArray(params MyIntOrArray[] elements) => _elements = elements; public override bool Print() { if (_currentIndex >= _elements.Length) return true; if (_elements[_currentIndex].Print()) _currentIndex++; return _currentIndex >= _elements.Length; } }
优势
- 类型职责清晰:每个子类仅对应一种形态,避免无效状态组合
- 多态特性消除了原代码中的
AmIArray标记字段,结构更简洁 - 实例创建直观,比如构建需求示例:
var example = new MyIntArray( new MyIntArray(new MyInt(1), new MyInt(2), new MyInt(3)), MyNull.Instance, new MyInt(4), new MyInt(5), new MyIntArray(new MyInt(6), MyNull.Instance, new MyInt(7)) );
方案二:单类+静态工厂的实现
如果不想引入继承体系,可通过私有构造+静态工厂方法限制实例形态,避免无效状态:
public class MyIntOrArray { private readonly int? _intValue; private readonly MyIntOrArray[] _arrayValue; private readonly bool _isNull; private int _arrayIndex = 0; // 私有构造,仅允许通过静态方法创建实例 private MyIntOrArray(int? intValue, MyIntOrArray[] arrayValue, bool isNull) { _intValue = intValue; _arrayValue = arrayValue; _isNull = isNull; } // 创建int类型实例 public static MyIntOrArray FromInt(int value) => new MyIntOrArray(value, null, false); // 创建null类型实例 public static MyIntOrArray FromNull() => new MyIntOrArray(null, null, true); // 创建数组类型实例 public static MyIntOrArray FromArray(params MyIntOrArray[] elements) => new MyIntOrArray(null, elements, false); public bool Print() { if (_isNull) return true; if (_intValue.HasValue) { Console.WriteLine(_intValue.Value.ToString()); return true; } if (_arrayIndex >= _arrayValue.Length) return true; if (_arrayValue[_arrayIndex].Print()) _arrayIndex++; return _arrayIndex >= _arrayValue.Length; } }
优势
- 用静态工厂方法确保实例只能是三种合法形态之一,避免原代码中
Value和Values同时赋值的无效状态 - 结构紧凑,无需额外子类
- 调用方式直观:
var example = MyIntOrArray.FromArray( MyIntOrArray.FromArray(MyIntOrArray.FromInt(1), MyIntOrArray.FromInt(2), MyIntOrArray.FromInt(3)), MyIntOrArray.FromNull(), MyIntOrArray.FromInt(4), MyIntOrArray.FromInt(5), MyIntOrArray.FromArray(MyIntOrArray.FromInt(6), MyIntOrArray.FromNull(), MyIntOrArray.FromInt(7)) );
原实现的问题点
- 状态冗余:
Value和Values字段同时存在,可能出现既设置int值又设置数组的无效状态 - 实例不可复用:
InnerIndex作为实例私有字段,导致数组实例多次调用Print时会从上次的位置继续,无法重置 - 标记式设计:
AmIArray字段属于“标记式”判断,不如多态或明确状态区分的设计优雅
内容的提问来源于stack exchange,提问作者Grizzly
相关产品推荐
相关产品推荐

