0

I know that there is already a question about converting a multidimensional array into a one dimensional one, but all of the answers to it are inefficient. All of them are based around making a copy of the array, which is unnecessary. A multidimensional array (not jagged) is stored in a contiguous block of memory, so converting back and forth between a one dimensional interpretation of this block and a multidimensional interpretation should not involve copying the whole array, but instead should be essentially free. It should actually be possible to have the two arrays share the same memory, so that when one gets updated, the other one also does.

Can this be done in C#?

janekb04
  • 4,304
  • 2
  • 20
  • 51
  • You can convert from single dimension indices to two-dimensional indices and vice versa with some simple math. – Robert Harvey Jul 16 '20 at 15:49
  • @RobertHarvey I know I can do it myself, but I am asking if I can make the language do it for me. – janekb04 Jul 16 '20 at 15:50
  • Not without copying the arrays. Have a look here: https://stackoverflow.com/a/16790720 – Robert Harvey Jul 16 '20 at 15:51
  • 1
    Why do you feel you *need* both representations of the array? And is this for all types that an array can contain or some specific type (e.g. if you are talking *specifically* about `byte[]` for instance)? – Damien_The_Unbeliever Jul 16 '20 at 15:52
  • @Damien_The_Unbeliever The data is actually a 3D array. The problem is that I have a function that takes only one dimensional parameters as an argument that I must give this array to. In this case it is `UnityEngine.Texture3D.SetPixelData`. Because this is texture data it can only be made out of basic arithmetic types such as `byte`s, `int`s, `float`s, `uint`s and `struct`s made out of these types, such as `Vector3` (three floats) if that is possible. – janekb04 Jul 16 '20 at 15:58
  • Your question is really too broad, lacking any sort of constraints or specific problems you're trying to address, but the marked duplicates do address the basic question taken literally. Beyond that, features like `Buffer.BlockCopy()` and the judicious use of `unsafe` code can address specific scenarios. If you need help interacting with Unity3d specifically you should post a new question that includes a [mcve], an explanation of what _specific_ problem you are trying to solve, and what part of that problem you need help with. – Peter Duniho Jul 16 '20 at 16:45
  • See also https://stackoverflow.com/questions/28113015/c-sharp-convert-1d-array-to-2d and https://stackoverflow.com/questions/7265542/does-array-copy-work-with-multidimensional-arrays for possible additional insight. – Peter Duniho Jul 16 '20 at 16:46

2 Answers2

1

No, you cannot. Quite apart from anything else, arrays, like many things in .NET are objects. That means that they have an object header positioned immediately before other memory used for storing their representation.

Logically, you cannot have two different object headers, for two different types of objects, occupying the same location in memory.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
1

Well, the data itself if pretty much stored the same way, but the wrapping around that - the managed array type - is what's stopping you from accessing it directly.

The managed array, as Damien pointed out, has different headers for one or multidimensional kinds, for example, multidimensional array's header has more fields - to store the dimension values.

The arrays themselves are maintained by IL and GC and their "data memory" part could not be "frozen" so that the headers could be swapped from one to another, if you'd want to write directly to RAM to switch them.

I'm also concerned that there is an XY problem. Why indeed are you trying to convert one array to another? Is there a reason you cannot just use this instead?

public static T Get<T>(this T[] array, int x, int y, int maxX)
{
    return T[x + y * maxX];
}

Or even write your own wrapper around an array and provide both Get[index/indices] methods from there?

AgentFire
  • 8,944
  • 8
  • 43
  • 90
  • There is nothing stopping me from accessing the array manually, in the way you showed. I asked because I thought that it must be possible to do it somehow, as in C or C++ I could just do a quick `static_cast` to go around the type enforcement. It seems a little strange that there is nothing such as this in C#, but after all, its not really designed for low-level usage like uploading data to graphics memory. – janekb04 Jul 16 '20 at 16:11
  • @enthusiastic_3d_graphics_pr... I don't really see how uploading data to video memory is connected to how C# code access some array - via one index or two. The latter is just a question of convenience, in my opinion. – AgentFire Jul 16 '20 at 16:35