以编程方式声明任意等级的数组 [英] Programmatically Declare Array of Arbitrary Rank

查看:69
本文介绍了以编程方式声明任意等级的数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In C#, there are three types of arrays: one-dimensional, jagged, and multi-dimensional rectangular.

问题是:给定特定大小的数组,我们如何创建具有相同尺寸和等级的新数组?

The question is: given an array of a specific size, how can we create a new array with the same dimensions and rank?

对于多维矩形数组,似乎没有语法可以在运行时定义大小和等级(维数).

In the case of a multidimensional rectangular array, there appears to be no syntax by which it is possible to define the size and rank (number of dimensions) at runtime.

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

C# declares multidimensional arrays with commas in the indexers:

object[,,] myArray = new object[2,4,2];

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

In the above example, I can determine the shape of the array by invoking the Rank property and the size of each dimension by calling the GetLength method and passing the specified dimension.

但是,即使我可以确定myArray是2 x 4 x 2,如果我没有得到数组的等级,我如何以编程方式创建具有相同尺寸的数组的新实例,预先?

However, even though I can determine that myArray is 2 x 4 x 2, how can I programmatically create a new instance of an array with the same dimensions, if I am not given the rank of the array beforehand?

推荐答案

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

Use Array.CreateInstance(Type, Int32[]) method to create an array of an arbitrary size.

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

But the problem, you will have after creating this array is: How do you efficiently access the elements of the array if you don't know its rank?

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

You may use myArray.GetValue(Int32[]) and myArray.SetValue(Object, Int32[]) but I assume the performance is no that good.

总结:

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
}

更新

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

Update

I've done a little benchmark to compare performance of the array indexer and the GetValue, SetValue versions.

这是我使用的代码:

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);

结果是:

Indexer method: 0.014 s
Set/GetValue method: 1.33 s

如果将int替换为object,结果将略有不同.

The result are slightly different if I replace the int by object.

Indexer method: 0.05 s
Set/GetValue method: 0.54 s

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

This can be easily explained by the necessary boxing/unboxing when using integer with Set/GetValue.

这篇关于以编程方式声明任意等级的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆