如何获取子数组的引用

时间:2018-01-23 09:56:37

标签: c# .net arrays

我正在尝试从现有数组中获取子数组的引用。 我希望能够在子阵列上进行修改时更新原始数组。 示例:

byte[] array = {0 , 1, 2, 3, 4};
byte[] subarray = array.Skip(2).Take(3).ToArray();
subarray[0] = 8;
Console.WriteLine("array[2] = " + array[2]);

我想看看:

  

array [2] = 8

但相反,我得到:

  

array [2] = 2

我读了这个solution,但它不够好,因为我不想给出修改不在范围内的数组值的选项,如下所示:

ArraySegment<byte> segment = new ArraySegment<byte>(array, 2, 3);
byte[] segmentByte = segment.ToArray();

我可以通过segmentByte修改所有原始数组。这就是我想要阻止的。

3 个答案:

答案 0 :(得分:3)

您可以编写简单的ArrayArraySegment<of T>包装器,仅提供一组必需的操作:

struct StrictRangeArraySegment<T>
{
    ArraySegment<T> _segment;
    public StrictRangeArraySegment(T[] array) 
        : this(array, 0, array.Length)
    {
    }
    public StrictRangeArraySegment(T[] array, int offset, int count)
        : this(new ArraySegment<T>(array, offset, count))
    {
    }
    public StrictRangeArraySegment(ArraySegment<T> segment)
    {
        _segment = segment;
    }

    public int Count
    {
        get
        {
            return _segment.Count;
        }
    }

    public T this[int index]
    {
        get
        {
            if (index < 0 || index >= _segment.Count)
                throw new ArgumentOutOfRangeException(nameof(index));
            return _segment.Array[_segment.Offset + index];
        }
        set
        {
            if (index < 0 || index >= _segment.Count)
                throw new ArgumentOutOfRangeException(nameof(index));
            _segment.Array[_segment.Offset + index] = value;
        }
    }
}

有关参考,请参阅ArraySegment<Of T> source code

答案 1 :(得分:0)

如果仔细查看ToList方法,您会看到它完全生成一个新列表,而这个列表根本不会引用旧列表。因此,您更改的内容仅反映为subarray

唯一的解决方案是使用您不想要的ArraySegment

public List<TResult> ToList()
{
    var list = new List<TResult>();

    foreach (TSource item in _source)
    {
        list.Add(_selector(item));
    }
    return list;
}

答案 2 :(得分:0)

一个选项是创建一个类型,将整数作为对象的属性包装。然后更新属性将得到所需的结果:

public class Box<T>
{
    public T Value {get;set;}
    public Box<T>(T item) {Value = item;}
}

Box<byte>[] array = {new Box<byte>(0), new Box<byte>(1), new Box<byte>(2), new Box<byte>(3), new Box<byte>(4)};
Box<byte>[] subarray = array.Skip(2).Take(3).ToArray();
subarray[0].Value = 8;
Console.WriteLine("array[2] = " + array[2].Value);
//you'll see "8" instead of "2" now

您可能还想查看Span<T>。它还没有完全发布,但它可能会在这里实现你的目标。