没有复制的c#数组切片

本文关键字:数组 切片 复制 | 更新日期: 2023-09-27 17:52:53

我想传递一个c#数组的子集到一个方法。我不关心这个方法是否覆盖了数据,所以我想避免创建一个副本。

有办法做到这一点吗?

谢谢。

没有复制的c#数组切片

将方法更改为IEnumerable<T>ArraySegment<T>

可以通过new ArraySegment<T>(array, 5, 2)

在c# 7.2中,我们有Span<T>。您可以为您的数组使用扩展方法AsSpan<T>,并将其传递给该方法,而不复制切片部分。如:

Method( array.AsSpan().Slice(1,3) )

可以使用下面的类。注意,您可能需要修改它,这取决于您希望endIndex是包含的还是排他的。您还可以将其修改为接受开始和计数,而不是开始和结束索引。

我故意没有添加可变方法。如果你特别想要它们,这很容易添加。如果你添加可变方法,你可能还想实现IList

public class Subset<T> : IReadOnlyList<T>
{
    private IList<T> source;
    private int startIndex;
    private int endIndex;
    public Subset(IList<T> source, int startIndex, int endIndex)
    {
        this.source = source;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }
    public T this[int i]
    {
        get
        {
            if (startIndex + i >= endIndex)
                throw new IndexOutOfRangeException();
            return source[startIndex + i];
        }
    }
    public int Count
    {
        get { return endIndex - startIndex; }
    }
    public IEnumerator<T> GetEnumerator()
    {
        return source.Skip(startIndex)
            .Take(endIndex - startIndex)
            .GetEnumerator();
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

数组是不可变的大小(即你不能改变数组的大小),所以你只能传递原始数组的减去的副本。作为选项,您可以将两个索引传递到原始数组的方法中,并根据额外的两个索引进行操作。

你可以使用Linq取函数从数组中取任意数量的元素

var yournewarray = youroldarray.Take(4).ToArray();