views:

206

answers:

2

Hello there,

I'm refactoring a library we currently use, and I'm faced with the following problem.

We used to have the following stuff :

class Blah
{
    float[][] data;
    public float[] GetDataReference(int index)
    {
        return data[index];
    }
}

For various reasons, I have replaced this jagged array version with a 1 dimensionnal array version, concatenating inner arrays. My question is : how can I still return a reference to a sub array of data ?

class Blah
{
    float[] data;
    int rows;

    public float[] GetDataReference(int index)
    {
        // Return a reference data from offset i to offset j;
    }
}

I was thinking that unsafe and pointers stuff may be of use, is it doable ?

+5  A: 

No, you can't do this - but you should look at using ArraySegment instead.

Note that an array object consists of metadata about its length etc and then the data itself. You can't create a slice of an existing array and still have the metadata next to the data, if you see what I mean - there'd have to be an extra level of indirection (which is what ArraySegment provides).

(I'm slightly surprised that ArraySegment doesn't do more wrapping, e.g. by implementing IList<T>, but there we go. It would be easy enough to create such a structure if you wanted to.)

Jon Skeet
+1 You learn something new everyday :-)
WestDiscGolf
Agreed, didn't know that either. I'll keep my answer (should work as well), but this seems to be the "right way" (tm)
Benjamin Podszun
The memory layout of a jagged array makes it impractical to use unsafe constructs to get to their contents. If multiple dimensional arrays were used, it can be done and can be beneficiary in (rare) corner cases where the poor .NET performance on multi dim arrays is too slow for you. But you still cannot return a slice without copying and adding the new metadata.
Abel
@Abel: I understand that it is not jagged, just a long single-dimensional array. Think the ImageData bytes[] that you have to map to rows again to get something at a specified x, y. That's how I got him at least.
Benjamin Podszun
Hum, I have already created a wrapper with some kind of IArray<T> : IEnumerable<T> interface. Works nicely but means that I'll have to change/check all calls to GetDataReference in the code... even some code I have no access to..
Wam
My remark was more-a-less meant in general, not to anyone in particular ;-). However, you (Benjamin) point at an interesting point: upon creation, a single-dimensional jagged array with each sub-array having the same size, has a memory layout usable with image processing or mathematics. However, only multi-dim arrays guarantee the layout, jagged arrays do not.
Abel
A: 

Check the following question on SO, but don't use the accepted answer (you don't want to copy after all), but rather follow the other options of using an Enumerator for the slice/subpart of the original array.

Array slices in C#

Benjamin Podszun