简体   繁体   中英

C# Changing the number of dimensions in an array

Is it possible, in C#, to convert a multi-dimensional array into a 1D array without having to copy all the elements from one to the other, something like:

int[,] x = new int[3,4];
int[] y = (int[])x;

This would allow the use of x as if it were a 12-element 1D array (and to return it from a function as such), but the compiler does not allow this conversion.

As far as I'm aware, a 2D array (or higher number of dimensions) is laid out in contiguous memory, so it doesn't seem impossible that it could work somehow. Using unsafe and fixed can allow access through a pointer, but this doesn't help with returning the array as 1D.

While I believe I can just use a 1D array throughout in the case I'm working on at present, it would be useful if this function was part of an adapter between something which returns a multidimensional array and something else which requires a 1D one.

You can't, it's not possible in C# to convert array's this way. You maybe could do it by using a external dll ( C/C++ ), but then you need to keep your array at a fixed location.

Speed

Generally i would advice to avoid using a 2D array because theese are slow in C#, better use jagged-array or even better single dimensionals with a little bit of math.

Int32[] myArray = new Int32[xSize * ySize];

// Access
myArray[x + (y * xSize)] = 5;

In C#, arrays cannot be resized dynamically. One approach is to use System.Collections.ArrayList instead of a native array. Another (faster) solution is to re-allocate the array with a different size and to copy the contents of the old array to the new array. The generic function resizeArray (below) can be used to do that.

One example here :

// Reallocates an array with a new size, and copies the contents
// of the old array to the new array.
// Arguments:
//   oldArray  the old array, to be reallocated.
//   newSize   the new array size.
// Returns     A new array with the same contents.
public static System.Array ResizeArray (System.Array oldArray, int newSize) {
   int oldSize = oldArray.Length;
   System.Type elementType = oldArray.GetType().GetElementType();
   System.Array newArray = System.Array.CreateInstance(elementType,newSize);
   int preserveLength = System.Math.Min(oldSize,newSize);
   if (preserveLength > 0)
      System.Array.Copy (oldArray,newArray,preserveLength);
   return newArray; }

You can already iterate over a multidim as if it were a 1 dimensional array:

  int[,] data = { { 1, 2, 3 }, { 3, 4, 5 } };

  foreach (int i in data)
     ...  // i := 1 .. 5

And you could wrap a 1-dim array in a class and provide an indexer property this[int x1, int x2] .

But everything else will require unsafe code or copying. Both will be inefficient.

Riding on the back of Felix K.'s answer and quoting a fellow developer:

You can't convert a square to a line without losing information

try

int[,] x = {{1, 2}, {2, 2}};
int[] y = new int[4];
System.Buffer.BlockCopy(x, 0, y, 0, 4);

您无法进行强制转换,必须复制以下元素:

int[] y = (from int i in y select i).ToArray();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM