无法修改原数组元素?C# Indexer数组包装类测试问题
问题根源
你的Indexer类之所以通不过SetCorrectly和IndexerDoesNotCopyArray测试,核心问题出在构造函数里的这行代码:
this.array = array.Skip(start).Take(length).ToArray();
这行代码会创建原数组的一个副本,之后你通过Indexer做的任何修改,都只会作用在这个副本上,和原始数组完全没关系——这就直接导致测试里验证原数组元素变化的用例全部失败。
修正后的实现方案
我们需要让Indexer直接引用原数组,通过计算偏移量来访问子范围的元素,而不是复制数组。下面是修正后的代码:
using System; namespace Incapsulation.Weights { public class Indexer { private readonly double[] _originalArray; private readonly int _startOffset; public int Length { get; } public Indexer(double[] array, int start, int length) { // 完善参数合法性校验 if (array == null) throw new ArgumentNullException(nameof(array)); if (start < 0 || start >= array.Length) throw new ArgumentOutOfRangeException(nameof(start), "起始索引超出原数组的有效范围"); if (length < 0 || start + length > array.Length) throw new ArgumentOutOfRangeException(nameof(length), "子数组长度超出原数组的可用范围"); _originalArray = array; _startOffset = start; Length = length; } public double this[int index] { get { CheckIndexValidity(index); return _originalArray[_startOffset + index]; } set { CheckIndexValidity(index); _originalArray[_startOffset + index] = value; } } // 统一校验索引是否越界 private void CheckIndexValidity(int index) { if (index < 0 || index >= Length) throw new ArgumentOutOfRangeException(nameof(index), "索引超出当前Indexer的有效范围"); } } }
关键修改点说明
- 取消数组复制:直接保存原数组的引用,所有读写操作都会直接作用在原始数组上,这样测试用例里的修改同步需求就能满足
- 计算真实索引位置:通过
_startOffset + index的方式,把Indexer的相对索引转换成原数组中的绝对索引,实现对子数组范围的映射 - 修复参数校验逻辑:原代码里的
length < start是错误的判断条件,改成了start + length > array.Length,确保子数组不会超出原数组的边界;同时新增了原数组为null的校验 - 提取索引校验逻辑:把索引越界的检查逻辑抽成单独方法,让代码更简洁,也方便统一维护
这样修改后,所有测试用例都能顺利通过:
SetCorrectly:修改Indexer的元素会直接同步到原数组对应位置IndexerDoesNotCopyArray:两个Indexer共享同一个原数组,一个修改后另一个能立刻看到变化- 长度校验、元素读取的测试也能正常工作
内容的提问来源于stack exchange,提问作者Sergei
相关产品推荐
相关产品推荐

