Link to part of an array in C #

I have an array containing some data, say, a header and real data. I need to pass the data contained in the array to a method, but I definitely want to avoid copying it to another array.

I was thinking of something like ArraySegment, but it doesn't seem to work in my case (or maybe I'm wrong?).

So how to pass part of an array to a method since it was an array?

Thank you for your responses!

Greetings

+3
arrays reference c # copy
Aug 30 '10 at 19:22
source share
5 answers

Skip and Take :

var subArray = array.Skip(5).Take(10); 
+6
Aug 30 '10 at 19:25
source share

If you want to stick only to basic arrays (i.e. int [] numbers), then the most efficient way is for your functions to take the offset / count directly .

There are many I / O functions that do something like this:

 readData(data, 0, 4); string readData(byte [] buffer, int offset, int length) 

Another option is to use IEnumberable <T> and use skip / take

 readData(data.Skip(0).Take(4)); string readData(IEnumerable<byte> buffer) 

It is important to remember that in C # you are not dealing with pointers ; you are dealing with objects .

+5
Aug 30 '10 at 19:29
source share

I had the same idea as Jon Skeet : implement a wrapper around T[] that provides random access by index, automatically processing the indexed access setting for you.

I recently put together a quick implementation (skip to the end of this answer for a short demonstration):

 public struct ArrayFragment<T> : IList<T> { private T[] _source; private int _start; private int _count; public ArrayFragment(T[] source, int start, int count) { if (source == null) { throw new ArgumentNullException("source"); } if (start < 0 || start >= source.Length) { throw new ArgumentOutOfRangeException("start"); } if (count > source.Length - start) { throw new ArgumentOutOfRangeException("count"); } _source = source; _start = start; _count = count; } public T this[int index] { get { return _source[_start + index]; } } public int Count { get { return _count; } } public bool Contains(T value) { int index = Array.IndexOf(_source, value, _start, _count); return index != -1; } public void CopyTo(T[] destination, int index) { Array.Copy(_source, _start, destination, index, _count); } public int IndexOf(T value) { int index = Array.IndexOf(_source, value, _start, _count); return index != -1 ? index - _start : -1; } public IEnumerator<T> GetEnumerator() { for (int i = 0; i < _count; ++i) { yield return _source[_start + i]; } } #region Explicit Interface Implementation // a bunch of explicitly implemented IList<T> members // that all throw a NotSupportedException #endregion } 

Here is a demo:

 int[] numbers = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; try { var fragment = new ArrayFragment<int>(numbers, 2, 5); Console.WriteLine("Iterating using foreach: "); foreach (int number in fragment) { Console.WriteLine(number); } Console.WriteLine("Iterating using for: "); for (int i = 0; i < fragment.Count; ++i) { Console.WriteLine(fragment[i]); } Console.WriteLine("Index of 4: {0}", fragment.IndexOf(4)); Console.WriteLine("Index of 1: {0}", fragment.IndexOf(1)); Console.WriteLine("Index of 9: {0}", fragment.IndexOf(9)); Console.WriteLine("Index of 7: {0}", fragment.IndexOf(7)); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.ReadLine(); 

Output:

 Iterating using foreach:
 3
 four
 5
 6
 7
 Iterating using for:
 3
 four
 5
 6
 7
 Index of 4: 1
 Index of 1: -1
 Index of 9: -1
 Index of 7: 4
+4
Aug 30 '10 at 19:59
source share

From what I see, you have two options:

  • Change the method you call (if you have an option). Instead of just accepting an array (or IEnumerable), you could take its array, start index, and end index.

  • Instead of passing an array, pass an IEnumerable that enumerates the desired range in your array (without creating a copy of the elements in the array). One way to do this:

 var slice = someArray.Skip(startIndex).Take(endIndex - startIndex); 
+3
Aug 30 '10 at 19:28
source share

One option is to implement something like ReadOnlyCollection<T> from the point of view of IList<T> implementation in the same way, but expose it to “view” the existing collection, accordingly moving any access to the index (and with the corresponding account and etc.)).

This will probably be a pretty handy wrapper class. Then you change your method to accept the appropriate IList<T> instead of an array.

0
Aug 30 '10 at 19:41
source share



All Articles