以编程方式声明任意等级数组

nic*_*las 3 c# arrays

在C#中,有三种类型的数组:一维,锯齿状和多维矩形.

问题是:给定一个特定大小的数组,我们如何创建一个具有相同维度和排名的新数组?

在多维矩形阵列的情况下,似乎没有语法可以在运行时定义大小和等级(维数).

C#在索引器中声明带有逗号的多维数组:

object[,,] myArray = new object[2,4,2];
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我可以Rank通过调用GetLength方法并传递指定的维度来调用每个维度的属性和大小来确定数组的形状.

但是,即使我可以确定它myArray是2 x 4 x 2,如果我没有预先给出数组的等级,我怎么能以编程方式创建具有相同尺寸的数组的新实例

Céd*_*non 6

使用Array.CreateInstance(Type, Int32[])方法创建任意大小的数组.

但问题是,在创建此数组之后,您将拥有:如果您不知道它的排名,您如何有效地访问数组的元素?

您可以使用myArray.GetValue(Int32 [])myArray.SetValue(Object,Int32 []),但我认为性能不是那么好.

总结一下:

public static Array CreateArray(Array array)
{
    // Gets the lengths and lower bounds of the input array
    int[] lowerBounds = new int[array.Rank];
    int[] lengths = new int[array.Rank];
    for (int numDimension = 0; numDimension < array.Rank; numDimension++)
    {
        lowerBounds[numDimension] = array.GetLowerBound(numDimension);
        lengths[numDimension] = array.GetLength(numDimension);
    }

    Type elementType = array.GetType().GetElementType();  // Gets the type of the elements in the input array

    return Array.CreateInstance(elementType, lengths, lowerBounds);    // Returns the new array
}
Run Code Online (Sandbox Code Playgroud)

更新

我已经做了一些基准测试来比较数组索引器和GetValue,SetValue版本的性能.

这是我使用的代码:

const int size = 10000000;
object[] array1 = new object[size];
object[] array2 = new object[size];

Random random;
random = new Random(0);
for (int i = 0; i < size; i++)
{
    array1[i] = random.Next();
    array2[i] = random.Next();
}

Stopwatch stopwatch = new Stopwatch();

Console.ReadKey();
stopwatch.Restart();
for (int i = 0; i < size; i++)
    array1[i] = array2[i];
stopwatch.Stop();
Console.WriteLine("Indexer method: {0}", stopwatch.Elapsed);

random = new Random(0);
for (int i = 0; i < size; i++)
{
    array1[i] = random.Next();
    array2[i] = random.Next();
}

Console.ReadKey();
stopwatch.Restart();
for (int i = 0; i < size; i++)
    array1.SetValue(array2.GetValue(i), i);
stopwatch.Stop();
Console.WriteLine("Get/SetValue method: {0}", stopwatch.Elapsed);
Run Code Online (Sandbox Code Playgroud)

结果是:

Indexer method: 0.014 s
Set/GetValue method: 1.33 s
Run Code Online (Sandbox Code Playgroud)

如果我替换了intby ,结果会略有不同object.

Indexer method: 0.05 s
Set/GetValue method: 0.54 s
Run Code Online (Sandbox Code Playgroud)

使用整数时,可以通过必要的装箱/拆箱轻松解释这一点Set/GetValue.