Pobieranie pod-tablicy z istniejącej tablicy


335

Mam tablicę X zawierającą 10 elementów. Chciałbym utworzyć nową tablicę zawierającą wszystkie elementy z X, które zaczynają się od indeksu 3, a kończą na indeksie 7. Jasne, że mogę łatwo napisać pętlę, która to zrobi za mnie, ale chciałbym zachować mój kod tak czysty, jak to możliwe . Czy istnieje metoda w C #, która może to dla mnie zrobić?

Coś w stylu (pseudo kod):

Array NewArray = oldArray.createNewArrayFromRange(int BeginIndex , int EndIndex)

Array.Copynie pasuje do moich potrzeb . Potrzebuję elementów z nowej tablicy, aby były klonami. Array.copyto tylko memcpyodpowiednik w stylu C. Nie szukam tego.



7
@Kirtan - ten „dup” konkretnie chce IEnumerable <T> - który jest inny i ma inne optymalne rozwiązania; IMO
Marc Gravell

Tak więc, dwa wiersze potrzebne do zadeklarowania nowej tablicy i wywołania .Copy () nie są „czystym kodem”?
Ed S.

2
@Ed Swangren - nie, jeśli musisz to zrobić w środku przykuty wyrazem, nie ;-p
Marc Gravell

2
Odpowiedź ShaggyUka ​​jest prawdopodobnie poprawna: stackoverflow.com/questions/943635/...
Dykam

Odpowiedzi:


469

Możesz dodać go jako metodę rozszerzenia:

public static T[] SubArray<T>(this T[] data, int index, int length)
{
    T[] result = new T[length];
    Array.Copy(data, index, result, 0, length);
    return result;
}
static void Main()
{
    int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int[] sub = data.SubArray(3, 4); // contains {3,4,5,6}
}

Zaktualizuj klonowanie (co nie było oczywiste w pierwotnym pytaniu). Jeśli naprawdę chcesz głębokiego klona; coś jak:

public static T[] SubArrayDeepClone<T>(this T[] data, int index, int length)
{
    T[] arrCopy = new T[length];
    Array.Copy(data, index, arrCopy, 0, length);
    using (MemoryStream ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, arrCopy);
        ms.Position = 0;
        return (T[])bf.Deserialize(ms);
    }
}

Wymaga to jednak możliwości serializacji ( [Serializable]lub ISerializable) obiektów. Można łatwo zastąpić każdy inny serializatora jako właściwy - XmlSerializer, DataContractSerializer, protobuf netto itp

Zauważ, że głęboki klon jest trudny bez serializacji; w szczególności ICloneabletrudno jest zaufać w większości przypadków.


1
(oczywiście użycie indeksu końcowego zamiast długości jest prostą zmianą; opublikowałem „tak jak jest”, ponieważ jest to bardziej „typowe” użycie)
Marc Gravell

1
Potem ... twardy; nie robi tego .... prawdopodobnie trzeba by użyć serializacji, aby osiągnąć coś podobnego
Marc Gravell

1
zobacz moją odpowiedź na kilka alternatyw i link do kilku implementacji. część robienia tego z podrzędną tablicą jest naprawdę dość trywialna, tak naprawdę chcesz bitu klonującego i jest to złożone i nieco otwarte pytanie, które zależy całkowicie od twoich oczekiwań co do tego, jakie „prawidłowe” powinno być zachowanie .
ShuggyCoUk

2
To jest miłe. I szczególnie dobrze jest zauważyć, że ICloneable jest zawodny, bo och, tak jest zawsze.
Marcus Griep

1
Dziękujemy za podkreślenie problemów z głębokim klonowaniem w języku C #. Szkoda, bo głębokie kopiowanie jest podstawową operacją .
Dimitri C.

316

Możesz użyć Array.Copy(...)do skopiowania do nowej tablicy po jej utworzeniu, ale nie sądzę, że istnieje metoda, która tworzy nową tablicę i kopiuje zakres elementów.

Jeśli używasz .NET 3.5 Państwo mogli używać LINQ:

var newArray = array.Skip(3).Take(5).ToArray();

ale będzie to nieco mniej wydajne.

Zobacz odpowiedź na podobne pytanie, aby uzyskać informacje na temat bardziej szczegółowych sytuacji.


+1 Podoba mi się również ta odmiana. Jon, czy możesz wyjaśnić, dlaczego uważa się to za mniej wydajne?
Ian Roke

@Jon: Aby pasować do pytania, czy nie brzmiałoby to „Take (5)”? @Ian: Podejście Array.Copy nie wymaga wyliczenia i najprawdopodobniej będzie zwykłą memcopy ...
Marc Gravell

@Marc: Tak, rzeczywiście. Zbyt wiele pytań przeczesuje :)
Jon Skeet

11
@Ian: Metoda LINQ wprowadza dwa poziomy pośredni (iteratory), musi wyraźnie pomijać elementy i nie wie, jak duża będzie ostateczna tablica. Zastanów się nad drugą połową tablicy złożonej z dwóch milionów elementów: proste podejście „stwórz tablicę docelową, skopiuj” po prostu skopiuje wymagany blok bez dotykania innych elementów i za jednym razem. Metoda LINQ będzie przechodzić przez tablicę, aż osiągnie punkt początkowy, a następnie zacznie przyjmować wartości, budować bufor (zwiększając rozmiar bufora i okresowo kopiując). O wiele mniej wydajny.
Jon Skeet

jeśli 5 to EndIndexm, to poprawnym pytaniem jest array.Skip (3) .Take (5-3 + 1) .ToArray (); to znaczy. array.Skip (StartIndex) .Take (EndIndex-StartIndex + 1) .ToArray ();
Klaus78,

73

Czy zastanawiałeś się nad użyciem ArraySegment?

http://msdn.microsoft.com/en-us/library/1hsbd92d.aspx


1
Prawdopodobnie robi to, co chcesz, ale nie obsługuje domyślnej składni tablicy, ani nie obsługuje IEnumerable, więc nie jest szczególnie czysty.
Alex Black,

5
To wymaga więcej uznania. Według mnie exp kopiowanie ArraySegment jest również nieco szybsze (w końcu używam tablic do
rzeczy

5
@AlexBlack Wygląda jak na .NET 4.5 , implementuje IEnumerable<T>i wiele innych przydatnych interfejsów.
pswg

1
Jak użyłbyś ArraySegmentodpowiedzi na pierwotne pytanie?
Craig McQueen

2
@CraigMcQueen - Wypróbuj następujące podejście jednoliniowe:IList<T> newArray = (IList<T>)new ArraySegment<T>(oldArray, beginIndex, endIndex);
skia.heliou

36

Widzę, że chcesz wykonać Klonowanie, a nie tylko kopiowanie referencji. W takim przypadku możesz użyć .Selectdo rzutowania członków tablicy na ich klony. Na przykład, jeśli Twoje elementy zostały zaimplementowane, IClonablemożesz zrobić coś takiego:

var newArray = array.Skip(3).Take(5).Select(eachElement => eachElement.Clone()).ToArray();

Uwaga: To rozwiązanie wymaga .NET Framework 3.5.


To jest bardziej eleganckie.
smwikipedia

Właśnie tego szukałem. Działa to dla każdego IEnumerable. Mogę dostać IEnumerable, IList, IArrayitp ... z minimalnym zamieszanie, inline, jeśli muszę. Jeśli nie potrzebuję głębokiej kopii, po prostu usuwam Select. Upuszczenie Skiplub Takepozwala mi kontrolować zasięg. Alternatywnie, mogę to pomieszać z SkipWhilei / lub TakeWhile.
Mike

33

Poniższy kod robi to w jednym wierszu:

// Source array
string[] Source = new string[] { "A", "B", "C", "D" };
// Extracting a slice into another array
string[] Slice = new List<string>(Source).GetRange(2, 2).ToArray();

Podpisz linię i nie musisz dodawać Linq. To mój ulubiony sposób.
Dimitris,

Nadal nie klonuje źródła ... ale i tak jest to dobre podejście
IG Pascual

1
Powinien sklonować źródło, ponieważ ToArray: (1) tworzy nową tablicę i (2) wykonuje Array.Copy. Na koniec Source i Slice to dwa osobne obiekty. Takie podejście jest poprawne, jednak ja wolę Array.Copy: referencesource.microsoft.com/#mscorlib/system/collections/...
Krauss

13

W C # 8 wprowadzili nowy Rangei Indextyp

int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
var slice = a[i1..i2]; // { 3, 4, 5 }

12
string[] arr = { "Parrot" , "Snake" ,"Rabbit" , "Dog" , "cat" };

arr = arr.ToList().GetRange(0, arr.Length -1).ToArray();

8

Opierając się na odpowiedzi Marca, ale dodając pożądane zachowanie klonowania

public static T[] CloneSubArray<T>(this T[] data, int index, int length)
    where T : ICloneable
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Clone();            
    return result;
}

A jeśli implementacja ICloneable jest zbyt ciężka, to refleksyjna przy użyciu biblioteki Håvarda Strandena do kopiowania, aby wykonać wymagane ciężkie podnoszenie.

using OX.Copyable;

public static T[] DeepCopySubArray<T>(
    this T[] data, int index, int length)
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Copy();            
    return result;
}

Należy pamiętać, że implementacja OX.Copyable działa z dowolnym z:

Jednak aby kopia automatyczna działała, musi na przykład znajdować się jedno z poniższych stwierdzeń:

  • Jego typ musi mieć konstruktor bez parametrów lub
  • Musi to być kopia, lub
  • Musi mieć zarejestrowanego IInstanceProvider dla swojego typu.

Powinno to obejmować prawie każdą sytuację. Jeśli klonujesz obiekty, w których wykres podrzędny zawiera takie elementy, jak połączenia db lub uchwyty plików / strumieni, oczywiście masz problemy, ale jest to prawdą w przypadku każdej uogólnionej głębokiej kopii.

Jeśli zamiast tego chcesz zastosować inne podejście do głębokiego kopiowania, w tym artykule wymieniono kilka innych, więc sugeruję, aby nie próbować pisać własnego.


Pierwsze jest prawdopodobnie pożądanym rozwiązaniem, ponieważ prosi o klonowanie. Zauważ, że dzięki metodzie Copy prawdopodobnie nie musisz nawet sprawdzać, czy nie ma wartości null, ponieważ jest to metoda rozszerzenia, jeśli sama metoda już to robi. Warte spróbowania.
Dykam

Tak, zauważyłem zerowy czek, ale nie chciałem mylić OP na wypadek, gdyby nie odczytał źródła.
ShuggyCoUk

2
Tylko sidenote: Najnowsza wersja Copyable na GitHub nie wymaga, aby obiekty miały konstruktora bez parametrów. :) Zobacz github.com/havard/copyable
Håvard S

8

Możesz to zrobić dość łatwo;

    object[] foo = new object[10];
    object[] bar = new object[7];   
    Array.Copy(foo, 3, bar, 0, 7);  

Nie, pasek nadal będzie pusty. Array.Copy nie tworzy magicznie nowej tablicy, zwłaszcza że bar nie jest przekazywany z ref lub out.
Zr40

2
och, hej, masz rację, zrobiłem to w pośpiechu, ale hej, być może, kiedy piszesz krytykę, powinieneś skorygować, konstruktywna krytyka jest o wiele bardziej przydatna dla wszystkich. więc przed tym array.copy wykonujesz „bar = nowy obiekt [7];”
RandomNickName42

4

Myślę, że kod, którego szukasz to:

Array.Copy(oldArray, 0, newArray, BeginIndex, EndIndex - BeginIndex)


Myślę, że poznałem tu dobrego przyjaciela .... taka sama odpowiedź jak ty;) i dostałem dużo głosów! hah !! W każdym razie dobre czasy dobre czasy.
RandomNickName42

3

Alternatywnie do kopiowania danych możesz utworzyć opakowanie, które daje dostęp do części oryginalnej tablicy, tak jakby była kopią części tablicy. Zaletą jest to, że nie dostajesz kolejnej kopii danych w pamięci, a wadą jest niewielki narzut podczas uzyskiwania dostępu do danych.

public class SubArray<T> : IEnumerable<T> {

   private T[] _original;
   private int _start;

   public SubArray(T[] original, int start, int len) {
      _original = original;
      _start = start;
      Length = len;
   }

   public T this[int index] {
      get {
         if (index < 0 || index >= Length) throw new IndexOutOfRangeException();
         return _original[_start + index];
      }
   }

   public int Length { get; private set; }

   public IEnumerator<T> GetEnumerator() {
      for (int i = 0; i < Length; i++) {
        yield return _original[_start + i];
      }
   }

   IEnumerator IEnumerable.GetEnumerator() {
      return GetEnumerator();
   }

}

Stosowanie:

int[] original = { 1, 2, 3, 4, 5 };
SubArray<int> copy = new SubArray<int>(original, 2, 2);

Console.WriteLine(copy.Length); // shows: 2
Console.WriteLine(copy[0]); // shows: 3
foreach (int i in copy) Console.WriteLine(i); // shows 3 and 4

@Robert: Nie, nie jest. Spróbuj zamiast tego użyć ArraySegment, a zobaczysz, że nie możesz uzyskać dostępu do elementów według indeksu, ani iterować elementów.
Guffa

2

Array.ConstrainedCopy będzie działać.

public static void ConstrainedCopy (
    Array sourceArray,
    int sourceIndex,
    Array destinationArray,
    int destinationIndex,
    int length
)

2
To tylko kopiuje dane; nie utworzy nowej tablicy itp .; a jeśli tablica jest nowa, możemy użyć Array.Copy, która jest bardziej wydajna (nie ma potrzeby dodatkowych kontroli / wycofywania).
Marc Gravell

Zgadza się, ale utworzenie nowej macierzy to tylko jeden wiersz kodu i nie jest wymagana żadna nowa metoda. Zgadzam się, że Array.Copy również będzie działać.
crauscher

1

Nie ma jednej metody, która spełni Twoje oczekiwania. Musisz udostępnić metodę klonowania dla klasy w tablicy. Następnie, jeśli LINQ jest opcją:

Foo[] newArray = oldArray.Skip(3).Take(5).Select(item => item.Clone()).ToArray();

class Foo
{
    public Foo Clone()
    {
        return (Foo)MemberwiseClone();
    }
}

1

Co powiesz na użycie Array.ConstrainedCopy :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
Array.ConstrainedCopy(ArrayOne, 3, ArrayTwo, 0, 7-3);

Poniżej znajduje się mój oryginalny post. To nie zadziała

Możesz użyć Array.CopyTo :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
ArrayOne.CopyTo(ArrayTwo,3); //starts copy at index=3 until it reaches end of
                             //either array

1

Co powiesz na to:

public T[] CloneCopy(T[] array, int startIndex, int endIndex) where T : ICloneable
{
    T[] retArray = new T[endIndex - startIndex];
    for (int i = startIndex; i < endIndex; i++)
    {
        array[i - startIndex] = array[i].Clone();
    }
    return retArray;

}

Następnie musisz zaimplementować interfejs ICloneable we wszystkich klasach, na których musisz go używać, ale to powinno wystarczyć.


1

Nie jestem pewien, jak głęboko jest naprawdę, ale:

MyArray.ToList<TSource>().GetRange(beginningIndex, endIndex).ToArray()

Jest to trochę narzut, ale może wyeliminować niepotrzebną metodę.


1

C # 8 zapewnia funkcję o nazwie Range, aby uzyskać subarry od początku do końca indeksu. możesz użyć tego w ten sposób.

Index i1 = 3; // number 3 from beginning  
Index i2 = ^4; // number 4 from end  
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
var slice = a[i1..i2]; // { 3, 4, 5 }

To jakieś szalone pythonowe gówno. Kocham to.
Ch3shire

Tak, to naprawdę fajna funkcja
vivek nuna

0

Jeśli chodzi o klonowanie, nie sądzę, że serializacja wywołuje twoich konstruktorów. Może to zepsuć niezmienniki klasy, jeśli robisz ciekawe rzeczy w ctor's.

Wydaje się, że bezpieczniejszym rozwiązaniem są wirtualne metody klonowania wywołujące konstruktory kopii.

protected MyDerivedClass(MyDerivedClass myClass) 
{
  ...
}

public override MyBaseClass Clone()
{
  return new MyDerivedClass(this);
}

To, czy serializacja wywołuje konstruktorów, zależy od konkretnego serializatora. Niektórzy tak robią, inni nie. Ale te, które zwykle nie oferują obsługi oddzwaniania, aby umożliwić wykonanie wymaganych poprawek.
Marc Gravell

Podkreśla to kolejny punkt tarcia serializacji: Musisz podać domyślne konstruktory.
Hans Malherbe

0

Klonowanie elementów w tablicy nie jest czymś, co można zrobić w uniwersalny sposób. Czy chcesz głębokiego klonowania czy zwykłej kopii wszystkich członków?

Przejdźmy do podejścia „najlepszego wysiłku”: klonowania obiektów za pomocą interfejsu ICloneable lub serializacji binarnej:

public static class ArrayExtensions
{
  public static T[] SubArray<T>(this T[] array, int index, int length)
  {
    T[] result = new T[length];

    for (int i=index;i<length+index && i<array.Length;i++)
    {
       if (array[i] is ICloneable)
          result[i-index] = (T) ((ICloneable)array[i]).Clone();
       else
          result[i-index] = (T) CloneObject(array[i]);
    }

    return result;
  }

  private static object CloneObject(object obj)
  {
    BinaryFormatter formatter = new BinaryFormatter();

    using (MemoryStream stream = new MemoryStream())
    {
      formatter.Serialize(stream, obj);

      stream.Seek(0,SeekOrigin.Begin);

      return formatter.Deserialize(stream);
    }
  }
}

To nie jest idealne rozwiązanie, ponieważ po prostu nie ma takiego, który działałby dla dowolnego typu obiektu.


Czy nie powinno to być coś w rodzaju wyniku [i-index] = (T) ...?
Donald Byrd

tak :) I nie tylko. Granica pętli jest nieprawidłowa. Naprawię to. Dzięki!
Philippe Leybaert

0

Możesz wziąć udział w zajęciach wykonanych przez Microsoft:

internal class Set<TElement>
{
    private int[] _buckets;
    private Slot[] _slots;
    private int _count;
    private int _freeList;
    private readonly IEqualityComparer<TElement> _comparer;

    public Set()
        : this(null)
    {
    }

    public Set(IEqualityComparer<TElement> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<TElement>.Default;
        _comparer = comparer;
        _buckets = new int[7];
        _slots = new Slot[7];
        _freeList = -1;
    }

    public bool Add(TElement value)
    {
        return !Find(value, true);
    }

    public bool Contains(TElement value)
    {
        return Find(value, false);
    }

    public bool Remove(TElement value)
    {
        var hashCode = InternalGetHashCode(value);
        var index1 = hashCode % _buckets.Length;
        var index2 = -1;
        for (var index3 = _buckets[index1] - 1; index3 >= 0; index3 = _slots[index3].Next)
        {
            if (_slots[index3].HashCode == hashCode && _comparer.Equals(_slots[index3].Value, value))
            {
                if (index2 < 0)
                    _buckets[index1] = _slots[index3].Next + 1;
                else
                    _slots[index2].Next = _slots[index3].Next;
                _slots[index3].HashCode = -1;
                _slots[index3].Value = default(TElement);
                _slots[index3].Next = _freeList;
                _freeList = index3;
                return true;
            }
            index2 = index3;
        }
        return false;
    }

    private bool Find(TElement value, bool add)
    {
        var hashCode = InternalGetHashCode(value);
        for (var index = _buckets[hashCode % _buckets.Length] - 1; index >= 0; index = _slots[index].Next)
        {
            if (_slots[index].HashCode == hashCode && _comparer.Equals(_slots[index].Value, value))
                return true;
        }
        if (add)
        {
            int index1;
            if (_freeList >= 0)
            {
                index1 = _freeList;
                _freeList = _slots[index1].Next;
            }
            else
            {
                if (_count == _slots.Length)
                    Resize();
                index1 = _count;
                ++_count;
            }
            int index2 = hashCode % _buckets.Length;
            _slots[index1].HashCode = hashCode;
            _slots[index1].Value = value;
            _slots[index1].Next = _buckets[index2] - 1;
            _buckets[index2] = index1 + 1;
        }
        return false;
    }

    private void Resize()
    {
        var length = checked(_count * 2 + 1);
        var numArray = new int[length];
        var slotArray = new Slot[length];
        Array.Copy(_slots, 0, slotArray, 0, _count);
        for (var index1 = 0; index1 < _count; ++index1)
        {
            int index2 = slotArray[index1].HashCode % length;
            slotArray[index1].Next = numArray[index2] - 1;
            numArray[index2] = index1 + 1;
        }
        _buckets = numArray;
        _slots = slotArray;
    }

    internal int InternalGetHashCode(TElement value)
    {
        if (value != null)
            return _comparer.GetHashCode(value) & int.MaxValue;
        return 0;
    }

    internal struct Slot
    {
        internal int HashCode;
        internal TElement Value;
        internal int Next;
    }
}

i wtedy

public static T[] GetSub<T>(this T[] first, T[] second)
    {
        var items = IntersectIteratorWithIndex(first, second);
        if (!items.Any()) return new T[] { };


        var index = items.First().Item2;
        var length = first.Count() - index;
        var subArray = new T[length];
        Array.Copy(first, index, subArray, 0, length);
        return subArray;
    }

    private static IEnumerable<Tuple<T, Int32>> IntersectIteratorWithIndex<T>(IEnumerable<T> first, IEnumerable<T> second)
    {
        var firstList = first.ToList();
        var set = new Set<T>();
        foreach (var i in second)
            set.Add(i);
        foreach (var i in firstList)
        {
            if (set.Remove(i))
                yield return new Tuple<T, Int32>(i, firstList.IndexOf(i));
        }
    }

0

Przekonałem się, że jest to optymalny sposób:

private void GetSubArrayThroughArraySegment() {
  int[] array = { 10, 20, 30 };
  ArraySegment<int> segment = new ArraySegment<int>(array,  1, 2);
  Console.WriteLine("-- Array --");
  int[] original = segment.Array;
  foreach (int value in original)
  {
    Console.WriteLine(value);
  }
  Console.WriteLine("-- Offset --");
  Console.WriteLine(segment.Offset);
  Console.WriteLine("-- Count --");
  Console.WriteLine(segment.Count);

  Console.WriteLine("-- Range --");
  for (int i = segment.Offset; i <= segment.Count; i++)
  {
    Console.WriteLine(segment.Array[i]);
  }
}

Mam nadzieję, że to pomoże!


0

użyj metody rozszerzenia:

public static T[] Slice<T>(this T[] source, int start, int end)
    {
        // Handles negative ends.
        if (end < 0)
        {
            end = source.Length + end;
        }
        int len = end - start;

        // Return new array.
        T[] res = new T[len];
        for (int i = 0; i < len; i++)
        {
            res[i] = source[i + start];
        }
        return res;
    }

i możesz z niego korzystać

var NewArray = OldArray.Slice(3,7);

0

Kod z System.Private.CoreLib.dll:

public static T[] GetSubArray<T>(T[] array, Range range)
{
    if (array == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
    }
    (int Offset, int Length) offsetAndLength = range.GetOffsetAndLength(array.Length);
    int item = offsetAndLength.Offset;
    int item2 = offsetAndLength.Length;
    if (default(T) != null || typeof(T[]) == array.GetType())
    {
        if (item2 == 0)
        {
            return Array.Empty<T>();
        }
        T[] array2 = new T[item2];
        Buffer.Memmove(ref Unsafe.As<byte, T>(ref array2.GetRawSzArrayData()), ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), item), (uint)item2);
        return array2;
    }
    T[] array3 = (T[])Array.CreateInstance(array.GetType().GetElementType(), item2);
    Array.Copy(array, item, array3, 0, item2);
    return array3;
}



0

Nie spełnia twoich wymagań dotyczących klonowania, ale wydaje się łatwiejsze niż wiele odpowiedzi do zrobienia:

Array NewArray = new ArraySegment(oldArray,BeginIndex , int Count).ToArray();

-1
public   static   T[]   SubArray<T>(T[] data, int index, int length)
        {
            List<T> retVal = new List<T>();
            if (data == null || data.Length == 0)
                return retVal.ToArray();
            bool startRead = false;
            int count = 0;
            for (int i = 0; i < data.Length; i++)
            {
                if (i == index && !startRead)
                    startRead = true;
                if (startRead)
                {

                    retVal.Add(data[i]);
                    count++;

                    if (count == length)
                        break;
                }
            }
            return retVal.ToArray();
        }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.