【问题标题】:How can I dynamically generate and populate a multi-dimensional array如何动态生成和填充多维数组
【发布时间】:2015-12-28 03:19:18
【问题描述】:

我正在开发一个序列化程序,但遇到了多维数组的真实墙。如果我使用Activator.CreateInstance(),它会创建一个一维数组就好了,但是在如下使用时它无法工作:

var indices = new[] { 2, 2 };
Type type = typeof(int[,]);
var result = Activator.CreateInstance(type, indices) as Array;

如果我改用Array.CreateInstance() 来生成我的数组,它同样适用于单维和多维数组。但是,我对数组上用于动态设置值的SetValue() 方法的所有调用都会生成一个异常,而它在我使用Activator.CreateInstance() 创建的一维数组上运行良好。我真的很难找到一个可行的解决方案,它允许我动态创建任何维度/大小的数组,然后用值填充数组。我希望有更多 reflection 经验的人可以对此有所了解。

尝试使用 Activator 创建多维数组时出现异常:

找不到类型“System.Int32[,]”的构造函数。

当我改为使用 Array.CreateInstance() 然后调用 SetValue() 时,我从 SetValue() 调用中得到以下异常:

对象不能存储在这种类型的数组中。

坦率地说,这对我来说毫无意义,因为值是 int 而数组是 int[,]。

我正在为我的项目使用 4.5 框架,尽管我也用 4.6 重新创建了问题。

【问题讨论】:

  • 我怀疑Array.CreateInstance(type, indices) 给了你这个错误,因为它没有你期望的类型。调用它实际上会给你一个int[,][,],而不是int[,]
  • 进一步考虑,这可能是an X-Y problem。您能否添加一个示例,说明您的传入数据是什么样的,以及您实际上希望它如何作为对象?例如,如果您的传入数据更像jagged array than a rectangular matrix,那么您可能需要一个非常不同的答案。
  • 在这个特定的实例中,我正在编写一个序列化程序,它需要序列化/反序列化任何类型的用户数据(包括多维数组)。问题在于反序列化序列化数据。你确实是对的。看了这么久,我有点狭隘的眼光,一直认为它是 [,] 但在你指出之后我意识到它确实是在返回一个数组数组。

标签: c# .net arrays multidimensional-array reflection


【解决方案1】:

您可以使用实际的ElementType 调用Array.CreateInstance,在这种情况下为int

var indices = new[] { 2, 3 };                
var arr = Array.CreateInstance(typeof(int), indices);

然后您可以毫无例外地使用SetValue 填充数组。例如

var value = 1;
for (int i = 0; i < indices[0]; i++)
{
    for (int j = 0; j < indices[1]; j++)
    {
        arr.SetValue(value++, new[] { i, j });
    }
}

//arr = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]

【讨论】:

  • 这似乎不能推广到“任何维度/大小的数组”,因为每个索引都需要一个 for 循环。
  • @Bobson 不是。它只是展示了如何创建一个多维数组,因为那是 OP 的问题。对于 setValue 部分,我只是表明它在正确编写时不会引发异常。为清晰起见进行了编辑。
  • 啊,这是有道理的,我一直认为这两个 CreateInstance 方法是相同的,而不是认为 Array.CreateInstance 显然需要数组元素类型而不是数组类型。谢谢你们两位,确实解决了这个问题。
猜你喜欢
  • 2017-10-12
  • 2020-09-27
  • 2016-08-07
  • 2018-01-27
  • 2011-01-11
  • 1970-01-01
  • 2015-06-05
相关资源
最近更新 更多