С # Массив без копии

Я хотел бы передать подмножество массива C # в метод. Меня не волнует, перезаписывает ли метод данные, поэтому я бы хотел избежать создания копии.

Есть ли способ сделать это?

Спасибо.


person user1400716    schedule 14.01.2013    source источник
comment
Возможно, вас заинтересует ArraySlice ‹T›: github.com/henon/SliceAndDice   -  person henon    schedule 04.05.2019


Ответы (5)


Измените метод, чтобы использовать IEnumerable<T> или ArraySegment<T>.

Затем вы можете пройти new ArraySegment<T>(array, 5, 2)

person SLaks    schedule 14.01.2013
comment
Вы можете добавить пример IEnumerable<T> с Skip / Take. - person Stefan Steinegger; 14.01.2013
comment
@StefanSteinegger: ArraySegment<T> реализует IEnumerable<T> - person SLaks; 14.01.2013
comment
Однако вы теряете быстрый доступ к элементам при использовании ArraySegment, который реализует IEnumerable, IList, оба из которых не гарантируют O (1) для доступа к случайному элементу, верно? - person Tom; 05.08.2014
comment
@t: ArraySegment<T> - это O (1). referenceource.microsoft.com/#mscorlib/system/ - person SLaks; 05.08.2014

В C # 7.2 у нас есть Span<T>. Вы можете использовать метод расширения AsSpan<T> для своего массива и передать его методу, не копируя нарезанную часть. например:

Method( array.AsSpan().Slice(1,3) )
person uygar donduran    schedule 07.08.2019

Вы можете использовать следующий класс. Обратите внимание, что вам может потребоваться изменить его в зависимости от того, хотите ли вы, чтобы 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();
    }
}
person Servy    schedule 14.01.2013

Массивы неизменяемы по размеру (т.е. вы не можете изменить размер массива), поэтому вы можете передавать только вычтенную копию исходного массива. Как вариант, вы можете передать в метод два индекса в сторону исходного массива и работать на основе двух дополнительных индексов.

person Ilya Ivanov    schedule 14.01.2013

вы можете использовать Linq take funktion и брать столько элементов из массива, сколько хотите

var yournewarray = youroldarray.Take(4).ToArray();
person COLD TOLD    schedule 14.01.2013
comment
Если вы добавите ToArray в конец, вы выполните копию. Вам также нужно будет использовать как Skip, так и Take, чтобы получить произвольное подмножество. Наконец, если ему нужен быстрый индексированный доступ к подмножеству, он не получит его от IEnumerable. - person Servy; 14.01.2013
comment
-1: ОП специально написал, что он не хочет копию. - person Tom; 05.08.2014