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

如何不复制原数组截取子数组?C#索引器实现疑问

避免数组复制,直接访问原数组子区间的解决方案

嘿,我懂你不想复制数组的需求——毕竟额外的内存开销和复制操作完全没必要!你的核心问题在于构造函数里用了ToList().GetRange(start, length).ToArray(),这会直接创建原数组的副本。咱们可以换个思路,保存原数组的引用,同时记录子数组的起始位置和长度,然后通过索引器做偏移来直接访问原数组的对应元素,完全不用复制。

修改后的代码

public class Indexer
{
    // 保存原数组的引用,不做复制
    private readonly double[] _originalArray;
    // 子数组在原数组中的起始索引
    private readonly int _startIndex;
    // 子数组的长度
    private readonly int _length;

    public double this[int index]
    {
        get
        {
            // 检查索引是否在子数组的合法范围内
            if (index < 0 || index >= _length)
                throw new IndexOutOfRangeException("索引超出子数组范围");
            // 直接访问原数组的对应位置(起始索引 + 当前索引)
            return _originalArray[_startIndex + index];
        }
        set
        {
            if (index < 0 || index >= _length)
                throw new IndexOutOfRangeException("索引超出子数组范围");
            _originalArray[_startIndex + index] = value;
        }
    }

    public int Length => _length;

    public Indexer(double[] array, int start, int length)
    {
        // 增强参数合法性校验
        if (array == null)
            throw new ArgumentNullException(nameof(array));
        if (start < 0 || length < 0 || start + length > array.Length)
            throw new ArgumentException("起始位置或长度参数不合法");

        // 仅保存原数组引用和参数,不复制数组
        _originalArray = array;
        _startIndex = start;
        _length = length;
    }
}

关键改动说明

  • 移除数组复制操作:构造函数不再创建新数组,只保存原数组的引用、起始位置和子数组长度,几乎没有额外内存开销。
  • 索引器偏移处理:在get和set逻辑中,把用户传入的index转换成原数组的实际索引(_startIndex + index),直接操作原数组的对应元素。
  • 强化边界检查:除了构造函数的参数校验,索引器内部也增加了范围检查,避免用户访问超出子数组的位置。

注意事项

这种方案的小权衡是:通过Indexer修改元素会直接影响原数组,因为咱们操作的是原数组的引用。如果你的需求是让子数组和原数组完全隔离(修改子数组不影响原数组),那复制是不可避免的;但如果只是需要一个“视图”式的访问入口,这个方案就完美匹配你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:08:36