6

My question is similar to Getting a sub-array from an existing array although a little different notion is very important in my case - I can't use memory copying.

Let's say I have array X of 10000 elements, I need array Y that would contains 9000 elements from X, starting from X's index 500.

But I don't want to copy part of X to new array Y, so I don't want to use Array.Copy, Array.Clone, System.Block.Copy, IEnumerables etc. I want Y to be reference to X - Y[0] would be in fact X[500], Y[1] corresponds to X[501], ..., Y[9000] is X[9500].

Thus, for example changing value of X[100] would at the same time change value of Y[600]. How can I achieve this in C#?

5
  • Of course, you can use unsafe operations (like to C++ pointers), but it's not recommended. Commented Jun 1, 2015 at 10:22
  • 2
    Have you considered making a simple wrapper that acts like an array? It wouldn't be an array, but if you wrote your code to use the wrapper instead you could create wrappers for smaller slices of the underlying bigger array. Commented Jun 1, 2015 at 10:23
  • Why can't you use memory copying? Is there a reason you can't pass the offset around (perhaps as part of a wrapper, like @LasseV.Karlsen suggests)? Commented Jun 1, 2015 at 10:26
  • With copying he would have 2 distinct arrays + the overhead of making the copy, both of which could be unwanted (he doesn't say why, that's just my own take on the problem) Commented Jun 1, 2015 at 10:26
  • If you can't copy elements, then perhaps initial choice to use array as a storage was wrong? Depends on how you going to use it you can implement IEnumerable while having inside just a List to hold/add/remove items. Commented Jun 1, 2015 at 10:28

3 Answers 3

7

You could wrap it in another object with something like this:

class View<T>
{
     private T[] _array;
     private long _start;
     private long _length;
     public View(T[] array, long start, long length) { ... }
     public T this[long index] 
     {
         get 
         {
             if (/*do bounds check here*/) 
             {
                 return _array[_start + index];
             }    
         }
     }
}

This won't be an array, but a projection of one.

Sign up to request clarification or add additional context in comments.

4 Comments

I don't think array indexes can be longs, only ints (in number that is), and I would make the view a struct since it will effectively hold 2 32-bit values + a memory reference, make it even cheaper. Additionally I would make the fields readonly, but other than that, this is exactly the solution I would pick myself.
Thank you, looks very promising :)
@xcoder37 For completeness, add support for IEnumerable<T> and IList<T> as well.
@xcoder37 even though it doesn't support indexers, ArraySegment<T> has a similar concept. msdn.microsoft.com/en-us/library/1hsbd92d%28v=vs.110%29.aspx
3

You can use an ArraySegment. Here's an example:

String[] X = { "one", "two", "three", "four", "five"};

ArraySegment<String> arraySegment = new ArraySegment<String>(X, 1,3); // will contain {"two", "three", "four"}
arraySegment.Array[arraySegment.Offset + 1] = "3"; // X will contain { "one", "two", "3", "four", "five"};
                             // and arraySegment.Array will contain {"two", "3", "four"}

Comments

0

Sadly ArraySegment<T> is sealed, else you could easily have extended it with the proper array-syntax, ie indexers and the likes.

If I were you I would go with ArraySegment<T> and if it doesn't have the proper requirements, like ElementAt(n) being to inefficient, just implement a better implementation. Ex:

public static class ArrayExtensions 
{
  // Getter using underlying array
  public static T GetValueAt<T>(this ArraySegment<T> array, int index)
  { // No safe checks here, would recommend them in production though
    return array.Array[array.Offset + index];
  }
  // Setter using underlying array
  public static void SetValueAt<T>(this ArraySegment<T> array, int index, T value)
  { // maybe we should check that the calculated index is valid? Or just blow up?
    array.Array[array.Offset + index] = value;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.