用程序声明任意秩的数组
本文关键字:数组 任意秩 声明 程序 | 更新日期: 2023-09-27 18:24:47
在C#中,有三种类型的数组:一维、锯齿状和多维矩形。
问题是:给定一个特定大小的数组,我们如何创建一个具有相同维度和级别的新数组?
在多维矩形数组的情况下,似乎没有语法可以在运行时定义大小和秩(维数)。
C#在索引器中用逗号声明多维数组:
object[,,] myArray = new object[2,4,2];
在上面的例子中,我可以通过调用Rank
属性来确定数组的形状,通过调用GetLength
方法并传递指定的维度来确定每个维度的大小。
然而,即使我可以确定myArray
是2 x 4 x 2,如果事先没有给定数组的秩,我如何通过编程创建具有相同维度的数组的新实例
使用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
}
更新
我做了一个小的基准测试来比较数组索引器和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);
结果是:
Indexer method: 0.014 s
Set/GetValue method: 1.33 s
如果我用object
代替int
,结果会略有不同。
Indexer method: 0.05 s
Set/GetValue method: 0.54 s
当将integer与Set/GetValue
一起使用时,这可以很容易地通过必要的装箱/取消装箱来解释。
您可以使用类似反射的方法:
- 通过调用
Array.CreateInstance
创建您的数组实例。这将为您提供一个Array
类的实例 - 调用
SetValue
为数组赋值 - 使用
GetValue
检索数组的任何元素
您可以根据现有数组填充一个长度数组(每个列一个),然后使用Array.CreateInstance(Type, int[])
。因此:
public static Array CreateNewArrayOfSameSize(Array input)
{
int[] lengths = new int[input.Rank];
for (int i = 0; i < lengths.Length; i++)
{
lengths[i] = input.GetLength(i);
}
return Array.CreateInstance(array.GetType().GetElementType(), lengths);
}
遗憾的是,没有一种方法可以一次性返回所有长度,但我看不到。此外,我很惊讶Array
上没有ElementType
属性,但它可能只是在躲避我。
请注意,这个并没有试图为每个维度保持与原始数组相同的上/下限,只是大小。