384

I have an array X of 10 elements. I would like to create a new array containing all the elements from X that begin at index 3 and ends in index 7. Sure I can easily write a loop that will do it for me but I would like to keep my code as clean as possible. Is there a method in C# that can do it for me?

Something like (pseudo code):

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

Array.Copy doesn't fit my needs. I need the items in the new array to be clones. Array.copy is just a C-Style memcpy equivalent, it's not what I'm looking for.

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
user88637
  • 11,790
  • 9
  • 37
  • 36

26 Answers26

504

You could add it as an extension method:

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}
}

Update re cloning (which wasn't obvious in the original question). If you really want a deep clone; something like:

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);
    }
}

This does require the objects to be serializable ([Serializable] or ISerializable), though. You could easily substitute for any other serializer as appropriate - XmlSerializer, DataContractSerializer, protobuf-net, etc.

Note that deep clone is tricky without serialization; in particular, ICloneable is hard to trust in most cases.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    (obviously using an end index rather than a length is a simple change; I've posted "as is" because that is the more "typical" usage) – Marc Gravell Jun 03 '09 at 08:39
  • what does Array.Copy does internally . is it shallow copy ? C-Style memcopy? – user88637 Jun 03 '09 at 13:51
  • Yes, it is a memcopy-type copy. – Lasse V. Karlsen Jun 03 '09 at 14:00
  • So what you are actually telling me is that Array.Copy is good only for primitives. – user88637 Jun 03 '09 at 14:09
  • No... just that with classes it'll copy the **reference** - it won't create a new instance. – Marc Gravell Jun 03 '09 at 14:59
  • but what if I want my references to be cloned? – user88637 Jun 03 '09 at 15:36
  • 1
    Then... tough; it doesn't do that.... you'd probably need to use serialization to achieve something similar – Marc Gravell Jun 03 '09 at 19:42
  • 1
    see my answer for some alternates and a link to several implementations. the part about doing it to a sub array is really rather trivial, what you really want is the *cloning* bit and that's a complex and somewhat open question which depends entirely on your _expectations of what 'correct' behaviour should be_. – ShuggyCoUk Jul 08 '09 at 16:17
  • this is a pretty creative way of doing a deep copy, very nice – Stan R. Jul 13 '09 at 20:22
  • 2
    This is nice. And it especially good to point out that ICloneable is unreliable, because oh, is it ever. – Marcus Griep Jul 14 '09 at 02:02
  • 1
    Thanks for underlining the problems with deep cloning in C#. It's a shame really, as [deep copying is a fundamental operation](http://stackoverflow.com/q/3351018/74612). – Dimitri C. Feb 22 '11 at 08:38
  • Does it fit .net 2 ? I got errors about missing System.Core dll. – Massimo Aug 26 '16 at 23:40
  • EGADS! Let's start with it only works if everything being serialized is`[Serializable]`. If you have a very complex object, you need to ask yourself why you need the deep copy. Otherwise, consider finding a way to use `struct` instead of `class`, so `Array.Copy` can work. Alternatively, implement `ICloneable` or implement some other clone/deep copy method on the objects and only clone/copy on use. – Mike Sep 14 '17 at 02:43
  • error: The name `Array` does not exist in the current context. – Aaron Franke Nov 03 '17 at 21:02
  • 1
    @AaronFranke I don't include common using directives in most code samples. Add `using System;` and it should work – Marc Gravell Nov 04 '17 at 13:46
348

You can use Array.Copy(...) to copy into the new array after you've created it, but I don't think there's a method which creates the new array and copies a range of elements.

If you're using .NET 3.5 you could use LINQ:

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

but that will be somewhat less efficient.

See this answer to a similar question for options for more specific situations.

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • +1 I like this variation too. Jon, can you expand on why this is deemed less efficient? – Ian Roke Jun 03 '09 at 09:28
  • @Jon: To match the question, wouldn't that be "Take(5)"? @Ian: the Array.Copy approach doesn't involve an enumerator, and will most-likely be a straight memcopy... – Marc Gravell Jun 03 '09 at 09:35
  • @Marc: Yes indeed. Too much question skimming :) – Jon Skeet Jun 03 '09 at 09:57
  • 14
    @Ian: The LINQ approach introduces two levels of indirection (the iterators), has to explicitly skip over items, and doesn't know how big the final array is going to be beforehand. Consider taking the second half of a two-million-element array: a simple "create target array, copy" approach will just copy the required block without touching the other elements, and in one go. The LINQ approach will walk through the array until it reaches the start point, then start taking values, building up a buffer (increasing the buffer size and copying periodically). Much less efficient. – Jon Skeet Jun 03 '09 at 09:59
  • if 5 is the EndIndexm, then the correct question is array.Skip(3).Take(5-3+1).ToArray(); ie. array.Skip(StartIndex).Take(EndIndex-StartIndex+1).ToArray(); – Klaus78 Dec 03 '14 at 16:01
76

Have you considered using ArraySegment?

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

Yves M.
  • 29,855
  • 23
  • 108
  • 144
waterlooalex
  • 13,642
  • 16
  • 78
  • 99
  • Fantastic! If this does what I think it does, this solves my problem exactly. – Robert P Oct 08 '09 at 15:25
  • 1
    It probably does what you want, but it doesn't support the default array syntax, nor does it support IEnumerable, so its not especially clean. – waterlooalex Oct 08 '09 at 15:57
  • 5
    This needs more upvote. In my own exp, ArraySegment copying is slightly faster too (after all I use arrays for speed critical stuffs).. – nawfal Nov 15 '12 at 13:17
  • 5
    @AlexBlack It looks like as of [.NET 4.5](http://msdn.microsoft.com/en-us/library/1hsbd92d(v=vs.110).aspx), it implements `IEnumerable` and a variety of other useful interfaces. – p.s.w.g Dec 26 '13 at 16:21
  • I totally agree with @nawfal, this does need more up voting and it seems that the language designers realized this is a common task now. It works just expected! – dragonfly02 Jan 10 '15 at 22:26
  • 1
    How would you use `ArraySegment` to answer the original question? – Craig McQueen Mar 18 '15 at 00:43
  • 2
    @CraigMcQueen - Try the following single-line approach: `IList newArray = (IList)new ArraySegment(oldArray, beginIndex, endIndex);` – nikodaemus Jul 21 '15 at 17:30
  • 1
    @CraigMcQueen - Since the OP asked for an array, you would use `var newArray = new ArraySegment(oldArray, beginIndex, endIndex - beginIndex).ToArray()`. The previous comment will give you a list (i.e. not an array) that has too many elements, since it is using endIndex where a count is expected. – Mike Sep 14 '17 at 01:18
  • 1
    This approach is only more performant if all of the following are true: you do not need a deep copy, you do not need an array and you are planning to use an enumerator to traverse the elements. Otherwise you will need multiple traversals, i.e. you are forced to do something like `new ArraySegment(oldArray, offset, count).Select(e => e.Clone()).ToArray()`. The approach given by @zvolkov offers a lot of flexibility, and if you can use a list instead of an array, then the approach by @eeerahul has good performance (even better if deep copy isn't required). – Mike Sep 14 '17 at 02:22
  • ArraySegment does not support clear or remove element types methods – Neeraj Singh Chouhan Oct 03 '19 at 09:37
39

I see you want to do Cloning, not just copying references. In this case you can use .Select to project array members to their clones. For example, if your elements implemented IClonable you could do something like this:

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

Note: This solution requires .NET Framework 3.5.

Kevin
  • 16,549
  • 8
  • 60
  • 74
Andriy Volkov
  • 18,653
  • 9
  • 68
  • 83
  • This is more elegant. – smwikipedia Mar 24 '14 at 05:56
  • This is exactly what I was looking for. This works for any `IEnumerable`. I can get an `IEnumerable`, `IList`, `IArray`, etc... with minimal fuss, inline if I need to. If I don't need the deep copy, I just remove the `Select`. Dropping `Skip` or `Take` allows me to control the range. Alternatively, I can mix it up with `SkipWhile` and/or `TakeWhile`. – Mike Sep 14 '17 at 00:49
33

The following code does it in one line:

// 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();
eeerahul
  • 1,629
  • 4
  • 27
  • 38
Volker
  • 1,753
  • 2
  • 18
  • 28
  • Singe line and no need to add Linq. It's my preferred way. – Dimitris Jun 12 '15 at 20:11
  • Still it doesn't clone the source... but it's a good approach anyway – I.G. Pascual Mar 23 '16 at 12:56
  • 1
    It should clone the source because ToArray: (1) creates a new array and (2) executes Array.Copy. In the end Source and Slice are two separate objects. The approach is correct, however, I prefer Array.Copy: http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs – Krauss Sep 04 '16 at 20:23
32

In C# 8, they've introduced a new Range and Index type, which can be used like this:

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 }

References:

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Prasanth Louis
  • 4,658
  • 2
  • 34
  • 47
13
string[] arr = { "Parrot" , "Snake" ,"Rabbit" , "Dog" , "cat" };

arr = arr.ToList().GetRange(0, arr.Length -1).ToArray();
OhBeWise
  • 5,350
  • 3
  • 32
  • 60
user3698437
  • 131
  • 1
  • 3
8

Building on Marc's answer but adding the desired cloning behaviour

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;
}

And if implementing ICloneable is too much like hard work a reflective one using Håvard Stranden’s Copyable library to do the heavy lifting required.

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;
}

Note that the OX.Copyable implementation works with any of:

For the automated copy to work, though, one of the following statements must hold for instance:

  • Its type must have a parameterless constructor, or
  • It must be a Copyable, or
  • It must have an IInstanceProvider registered for its type.

So this should cover almost any situation you have. If you are cloning objects where the sub graph contains things like db connections or file/stream handles you obviously have issues but that it true for any generalized deep copy.

If you want to use some other deep copy approach instead this article lists several others so I would suggest not trying to write your own.

Community
  • 1
  • 1
ShuggyCoUk
  • 36,004
  • 6
  • 77
  • 101
  • The first is probably the desired solution, as he is asking for cloning. Note that with the Copy method, you probably don't even have to check for null, as it is an extension method, if the method itself already does that thing. Worth a try. – Dykam Jul 11 '09 at 08:02
  • Yes I noted the null check but didn't want to confuse the OP in case he didn't read the source. – ShuggyCoUk Jul 11 '09 at 11:22
  • 2
    Just a sidenote: The latest version of Copyable on GitHub does not require objects to have a parameterless constructor. :) See http://github.com/havard/copyable – Håvard S Feb 02 '10 at 08:28
8

You can do this fairly easially;

    object[] foo = new object[10];
    object[] bar = new object[7];   
    Array.Copy(foo, 3, bar, 0, 7);  
cb88
  • 447
  • 3
  • 18
RandomNickName42
  • 5,923
  • 1
  • 36
  • 35
  • No, bar will still be null. Array.Copy doesn't magically create a new array, especially since bar isn't passed with ref or out. – Zr40 Jul 08 '09 at 16:16
  • 2
    oh ya hey, your right, i did this in a hurry whops, but hey, maybe when your writing critique's you should put the correction, constructuive critisism is so much more usefull for everybody. so before that array.copy you do a "bar = new object[7];" – RandomNickName42 Jul 11 '09 at 07:58
5

I think that the code you are looking for is:

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

Sean
  • 599
  • 3
  • 5
  • I think I've been making some good friend's here.... same answer as you ;) and I got voted down plenty!! hah!! Anyhow, good times good times. – RandomNickName42 Jul 14 '09 at 02:41
3

In C# 8.0, you can now do many fancier works including reverse indices and ranges like in Python, such as:

int[] list = {1, 2, 3, 4, 5, 6};
var list2 = list[2..5].Clone() as int[]; // 3, 4, 5
var list3 = list[..5].Clone() as int[];  // 1, 2, 3, 4, 5
var list4 = list[^4..^0].Clone() as int[];  // reverse index
Obsidian
  • 799
  • 1
  • 6
  • 18
3

As an alternative to copying the data you can make a wrapper that gives you access to a part of the original array as if it was a copy of the part of the array. The advantage is that you don't get another copy of the data in memory, and the drawback is a slight overhead when accessing the data.

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();
   }

}

Usage:

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
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • @Robert: No, it's not. Try to use an ArraySegment instead, and you see than you can neither access the items by index, not iterate throught the items. – Guffa Oct 08 '09 at 15:42
2

It does not meet your cloning requirement, but it seems simpler than many answers to do:

Array NewArray = new ArraySegment(oldArray,BeginIndex , int Count).ToArray();
Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
2

Array.ConstrainedCopy will work.

public static void ConstrainedCopy (
    Array sourceArray,
    int sourceIndex,
    Array destinationArray,
    int destinationIndex,
    int length
)
crauscher
  • 6,528
  • 14
  • 59
  • 85
  • 2
    That just copies the data; it won't create the new array etc; and if the array is new, we could use Array.Copy which is more efficient (no need for the additional checks/rollbacks). – Marc Gravell Jun 03 '09 at 08:38
  • Thats right, but creating a new Array is only one line of code and no new method is required. I agree that Array.Copy will work as well. – crauscher Jun 03 '09 at 08:48
1

There's no single method that will do what you want. You will need to make a clone method available for the class in your array. Then, if LINQ is an option:

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

class Foo
{
    public Foo Clone()
    {
        return (Foo)MemberwiseClone();
    }
}
Thorarin
  • 47,289
  • 11
  • 75
  • 111
1

How about useing 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);

Below is my original post. It will not work

You could use 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
Mike
  • 3,219
  • 23
  • 29
1

How about this:

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;

}

You then need to implement the ICloneable interface on all of the classes you need to use this on but that should do it.

RCIX
  • 38,647
  • 50
  • 150
  • 207
1

I'm not sure how deep it really is, but:

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

It's a bit of overhead, but it might cut out an unnecessary method.

SCNerd
  • 11
  • 1
0

Cloning elements in an array is not something that can be done in a universal way. Do you want deep cloning or a simple copy of all members?

Let's go for the "best effort" approach: cloning objects using the ICloneable interface or binary serialization:

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);
    }
  }
}

This is not a perfect solution, because there simply is none that will work for any type of object.

Philippe Leybaert
  • 168,566
  • 31
  • 210
  • 223
0

As far as cloning goes, I don't think serialization calls your constructors. This may break class invariants if you're doing interesting things in the ctor's.

It seems the safer bet is virtual clone methods calling copy constructors.

protected MyDerivedClass(MyDerivedClass myClass) 
{
  ...
}

public override MyBaseClass Clone()
{
  return new MyDerivedClass(this);
}
Hans Malherbe
  • 2,988
  • 24
  • 19
  • Whether serialization calls your constructors is up to the specific serializer. Some do, some don't. But those that don't typically offer callback support to allow you to do any fixups required. – Marc Gravell Jul 14 '09 at 04:12
  • This highlights another friction point of serialization: You have to provide default constructors. – Hans Malherbe Jul 14 '09 at 07:32
0

You can take class made by 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;
    }
}

and then

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));
        }
    }
Smagin Alexey
  • 305
  • 2
  • 6
0

This is the optimal way, I found, to do this:

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]);
  }
}

Hope It Helps!

OscarMas
  • 1
  • 1
0

use extention method :

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;
    }

and you can use it

var NewArray = OldArray.Slice(3,7);
Erwin Draconis
  • 764
  • 8
  • 20
0

Code from the 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
array1 = [5,6,7,8];

int[] array2 = new int[2];

Array.ConstrainedCopy(array1, 1, array2, 0, 2);

array2 = [6,7];

Array.ConstrainedCopy takes five (5) parameters:

  1. source array (sourceArray)

  2. starting index of source array (sourceIndex)

  3. destination array (destinationArray)

  4. starting index of destination array (destinationIndex)

  5. number of elements to copy (length)

-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();
        }