If you're willing to use unsafe, you can access the multi-dimensional array in linear order as a float*.
For example, this code:
var b = new float[2, 3, 4];
fixed (float* pb = &b[0,0,0])
{
float* p = pb;
for (int i = 0; i < 2*3*4; i++)
{
*p = i + 1;
p++;
}
}
This will initialize the array to sequential values. The values are stored in 'depth-first' ordering, so b[0, 0, 0], b[0, 0, 1], b[0, 0, 2], b[0, 0, 3], b[0, 1, 0], b[0, 1, 1], etc.
This does not, however, allow you to keep that pointer around or somehow 'cast it back' to a 1d managed array. This limited scope of fixed pointer blocks is a very deliberate limitation of the managed runtime.