You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#索引器测试问题求助:数组值异常及跨实例赋值失效

解决C#索引器测试中的两个问题

我来帮你逐个拆解问题并给出彻底的解决方案:

问题1:实例化indexer0后,indexer1输出3、3而非预期的2、3

根源分析

你的Index类存在两个核心问题:

  1. 共享数组引用:所有Index实例都直接使用传入的原始数组引用,没有独立副本,修改一个实例的数组会影响所有关联实例;
  2. 构造函数逻辑错误:构造函数不仅没有实现数组切片的预期功能,反而直接修改了原始数组的元素。第一次实例化indexer0时,已经把原始数组{1,2,3,4}修改为{2,3,3,4};第二次实例化indexer1时,又用这个被修改后的数组再次执行构造逻辑,最终把数组改成了{3,3,3,4},所以indexer1[0]和indexer1[1]都会输出3。

问题2:临时变量解决问题1后,indexer2的赋值无法同步到indexer3

根源分析

如果为了避免问题1给每个Index实例克隆一份独立数组,那么各个实例的数组完全隔离,修改一个实例的元素自然不会影响其他实例。但你的需求是让不同Index实例共享底层数据,所以克隆数组的思路不符合预期。


完整解决方案:将Index设计为原始数组的视图类

正确的思路是让Index类作为原始数组的切片视图:保存原始数组的引用,通过起始索引映射视图的索引到原始数组的对应位置,既不会修改原始数组的初始数据,又能实现不同视图间的数据同步。

修正后的Index类代码

class Index
{
    // 保存原始数组的引用,实现多视图数据同步
    private double[] _originalArray;
    // 当前视图在原始数组中的起始索引
    private int _startIndex;

    // 视图的元素个数
    public int Length { get; }

    // 索引器:将视图索引映射到原始数组的对应位置
    public double this[int x]
    {
        get
        {
            // 添加边界检查,避免越界异常
            if (x < 0 || x >= Length)
                throw new IndexOutOfRangeException("视图索引超出范围");
            return _originalArray[_startIndex + x];
        }
        set
        {
            if (x < 0 || x >= Length)
                throw new IndexOutOfRangeException("视图索引超出范围");
            _originalArray[_startIndex + x] = value;
        }
    }

    // 构造函数:初始化视图的原始数组、起始和结束索引
    public Index(double[] originalArray, int startIndex, int endIndex)
    {
        _originalArray = originalArray ?? throw new ArgumentNullException(nameof(originalArray), "原始数组不能为null");
        if (startIndex < 0 || startIndex >= originalArray.Length)
            throw new ArgumentOutOfRangeException(nameof(startIndex), "起始索引超出原始数组范围");
        if (endIndex < startIndex || endIndex >= originalArray.Length)
            throw new ArgumentOutOfRangeException(nameof(endIndex), "结束索引必须大于等于起始索引且不超出原始数组范围");

        _startIndex = startIndex;
        // 计算视图的元素个数
        Length = endIndex - startIndex + 1;
    }
}

测试代码运行结果

使用修正后的Index类,你的测试代码会输出符合预期的结果:

static void Main(string[] args)
{
    double[] array = { 1, 2, 3, 4 };
    var indexer0 = new Index(array, 1, 2);
    Console.WriteLine(indexer0.Length); // 输出2
    Console.WriteLine("Result = 2,3");

    var indexer1 = new Index(array, 1, 2);
    Console.WriteLine(indexer1[0]); // 输出2
    Console.WriteLine(indexer1[1]); // 输出3 → 问题1解决

    Console.WriteLine("Copy 25");
    var indexer2 = new Index(array, 1, 2);
    var indexer3 = new Index(array, 0, 2);
    indexer2[0] = 25; // 修改原始数组的索引1位置的值
    Console.WriteLine(indexer3[1]); // 输出25 → 问题2解决

    Console.WriteLine("Array");
    foreach (var item in array)
    {
        Console.WriteLine(item); // 输出1、25、3、4
    }
    Console.ReadKey();
}

方案优势

  1. 不破坏原始数组初始数据:构造函数仅初始化视图参数,不修改原始数组;
  2. 多视图数据同步:所有Index实例共享原始数组引用,修改一个视图的元素会同步到其他映射到同一位置的视图;
  3. 健壮性提升:添加了参数合法性检查和边界判断,避免越界异常。

内容的提问来源于stack exchange,提问作者Tibomso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:43:05