12

I am using C#, and it's rather annoying that I can't send an array starting from a certain point like in C++.

suppose this code:

int[] array = new int[32];
foobar (array + 4); //send array starting from the 4th place.

this is a weird syntax for C# because we don't have any usable pointers, but surely there's a way to do it? There's .Skip(), but I think it produces a new array, which is something I do not like.

What are my options?

Nefzen
  • 7,819
  • 14
  • 36
  • 34
  • 3
    FYI, skip doesn't produce a new array. It produces a new _array enumerator_ that has skipped past the first n entries. – Eric Lippert Jun 29 '09 at 01:47
  • 1
    What I've done when porting C++ code to C# that uses this idiom of interior pointers to an array is implement an immutable ArrayPtr struct which implements user-defined [] - + operators. The ArrayPtr class handles the details of figuring out what the right offsets are into the real array. – Eric Lippert Jun 29 '09 at 01:49
  • How did you determine that creating a new array is too much overhead ? – nos Jun 29 '09 at 15:47
  • because it's going to be bigger than 32 ints. – Nefzen Jun 29 '09 at 16:03
  • Possible duplicate: http://stackoverflow.com/questions/18622632/create-an-array-that-points-to-only-part-of-another-array – Jon Dec 24 '13 at 00:20

4 Answers4

18

You might want to pass it as an IEnumerable<int> rather than as an array. You can then use skip and it will simply move the iterator over the number of elements skipped. Used this way, you won't have to use ToArray() and create a copy of the portion of the array in question. Of course, IEnumerable may not be appropriate for what you want to do, but that's difficult to tell from your question.

public void FooBar( IEnumerable<int> bar )
{
  ...
}

int[] array = new int[32];
FooBar( array.Skip(4) );
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 2
    what's the overhead for turning an array into an enumerable? – Nefzen Jun 28 '09 at 23:02
  • 2
    http://msdn.microsoft.com/en-us/library/system.array.aspx In the .NET Framework version 2.0, the Array class implements the System.Collections.Generic.IList(T), System.Collections.Generic.ICollection(T), and System.Collections.Generic.IEnumerable(T) generic interfaces. The implementations are provided to arrays at run time, and therefore are not visible to the documentation build tools. – tvanfosson Jun 28 '09 at 23:33
  • 2
    Wouldn't have thought of this approach in a million years. Really elegant. +1 – JulianR Jun 29 '09 at 00:31
  • and the other way around? if I turn an Enumerable to an Array? – Nefzen Jun 29 '09 at 13:36
  • 2
    I'm pretty sure that it will make a copy of the elements in the enumeration and return it as an array. – tvanfosson Jun 29 '09 at 15:24
3

I can appreciate what you are trying to do but you can't (and shouldn't try to) send a reference to "part of an array." In C#, arrays are objects, not pointers. That's an important distinction. Sending a reference to "part of an object" just doesn't make sense.

How should "part of an object" act when you pass it to a method?

  • What would array.Length return?
  • What if the called method sorts the array (just it's part of the array)?
  • What if the array is self-referential (i.e. array elements references other parts of the array)? Are you somehow "locked out" of accessing array elements not passed into the method?
  • Does the called method now need to check a flag to know if they have the "full object?" That would break a lot of existing code.

If your method needs only part of the array (and you don't want to create a local copy), the best solution would be to pass the array reference and any other information you need to access the portion you need.

halfer
  • 19,824
  • 17
  • 99
  • 186
Robert Cartaino
  • 27,494
  • 6
  • 45
  • 67
  • yes, an array reference would be good. The method doesn't need to know it's working on a subset of the array, it only reads or writes on it. A reference to an array with the same interface would be great. Actually I think I can write that myself, but I don't think it is worth the extra overhead. – Nefzen Jun 28 '09 at 23:35
3

.NET has the System.ArraySegment wrapper – unfortunately, it's completely useless since it doesn't implement IEnumerable.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 2
    For the good news: in .net 4.5, ArraySegment will implement IEnumerable (as well as IList). –  Apr 20 '12 at 11:01
1

You could just pass the offset to the function itself as a parameter. The function will then simply loop through the elements from [array + offset] to array.Length. That, or copy the sub-array into a new array, but that is probably not optimal.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • Yeah, I like tv's suggestion better, but I don't know about "so ugly". It is pretty straitforward, what do you think array.Skip is doing? – Ed S. Jun 28 '09 at 22:37