在C#中创建一个二维数组的数组

14

我想创建一个二维数组来存储坐标点。

因此,我想要一个数组,其中每个索引返回一个二维数组,我将使用它作为xy

这是我尝试过的:

waypoints = new int[4][,]    {
        {{0},{6, 0}},
        {{1},{1, 1}},
        {{2},{1, 5}},
        {{3},{6, 5}}
    };

我知道这看起来可能很愚蠢,但我已经尝试在谷歌上查找,但没有得到任何好的结果。

它显示了一个错误:

"error CS0623:只能在变量或字段初始化器中使用数组初始化器。请尝试使用新表达式。"

我还尝试过这样写:

waypoints = new int[4][,] {
        new int[,] {6, 0},
        new int[,] {1, 1},
        new int[,] {1, 5},
        new int[,] {6, 5}
        };

出现了以下错误:

"error CS0846: 预期嵌套的数组初始化程序"


可能是此问题的重复:从二维数组初始化中省略C#中的new关键字 - ardila
1
为什么不创建一个 Vector2 结构体的列表或类似的东西呢?这样可能更容易处理并且从长远来看更简单。 - rhughes
1
@rhughes:更不用说更好的引用局部性(对于当前处理器中的L-n缓存来说是一个重要考虑因素),以及减少垃圾收集(因为数组是一个对象,而结构体不是)。 - Pieter Geerkens
4个回答

13

在初始声明中还需要一个花括号集合{}

var waypoints = new int[4][,]   {
    new int[,] {{6}, {0}},
    new int[,] {{1}, {1}},
    new int[,] {{1}, {5}},
    new int[,] {{6}, {5}}
};

这是因为对于这样的二维数组,数组中的每个元素被认为是一个数组进行初始化(尽管通常会针对数组的每个元素使用,如 val[0,0] = 4;)。
编辑(在评论反馈后):
int [][ ] 相比(称为 分散数组,即数组的数组成员可以是 不同大小 的数组),int[,] 是具有 固定维数 的二维数组。两者都是存储数组的数组,因此数组的每个元素都是一个数组。这就解释了为什么需要像上面那样再放置一对括号来初始化它。
这样初始化的二维数组将导致不同的维数(因此有多种初始化方法)。
int[,] val = new int[,] { { 6 }, { 0 } }; //resulting in int[2,1]
int[,] val = new int[,] { { 6, 0 } }; //resulting in int[1,2]

在任何一种情况下,都需要额外的花括号。

对于“锯齿数组”和多维、固定大小的数组之间的区别,已经有很多来自知名来源的好的解释和基准测试可供参考(链接1) (链接2) (链接3) (链接4) (链接5) (链接6) (链接7)。我理解,除了回答初始化失败的问题外,增加更多信息对此并没有意义(除非是问者感兴趣的)。

理解到该解决方案不适合存储坐标点(如OP所做)。上面的解释是为了解释他的初始化不起作用,而不是提供存储坐标点的最佳解决方案。至于存储坐标点,System.Drawing中的Point struct将更加适当(如评论所建议)。
使用二维数组来表示2D 笛卡尔坐标系中的单个点是一种"过度设计",因为一个一维数组已经能够存储计算机允许的尽可能多的数字,远远超过存储笛卡尔坐标系中的两个数字所需的数字。

谢谢!如果您能解释一下原因,我会很高兴 :) - MysticPing
我相信这个问题最好由Microsoft在MSDN中解释:https://social.msdn.microsoft.com/Forums/en-US/283a69b0-169f-4178-88ce-1b71079897a2/difference-between-simple-array-and-jagged-array?forum=csharplanguage PS:但是如果你想要存储点(point),也许值得使用“Point”类进行存储。 - Ian
我相信 new int[,] {{6,0}} 足以满足需求,并且可能更易读。 - ardila
@aardila 是的,因为它是二维的,所以这确实是“杀鸡焉用牛刀”。我们甚至可能只需要int[](我们已经可以存储超过2个数字了)。我的示例只是表明需要另一组花括号(用于2D数组)。但是对于处理几何点,我认为Point最适合 - 请参见其他答案。 - Ian

12

这个问题其实很简单。使用"System.Drawing.Point"类的实例即可。创建一个"Point"数组来存储坐标。创建数组的方法如下:

Point[] points = new Point[4];

要为数组分配一个值(例如在位置0),请使用以下代码。

points[0] = new Point(xvalue,yvalue);//Where "xvalue" and "yvalue" are integer variables.

要从点类的实例中获取X和Y值,请使用以下代码。

int xvalue = points[0].X;

int yvalue = points[0].Y;

顺便提一句,您可以使用这些点来为控件分配位置,但那是另一回事 ^_^


1
谢谢,我会查一下的! - MysticPing

2

这些数组是二维的,大小未知,初始化程序可以定义各种大小的数组:

        var waypoints = new int[4][,]   {
                new int[,] { {1, 2, 6}, {3, 4, 5} }, // two rows, 3 columns
                new int[,] { {1, 1}, {1, 2} } , // 2 x 2
                new int[,] { {1, 5} }, // 1 x 2
                new int[,] { {6, 5} }
                };

0

我可能误解了问题,但是你的数组不是多了一个维度吗?这有点像那些建议使用 Point 或 Vector 类的人的观点。如果每个数组只存储一个点(可能不是这样,我可能只是假设),你不需要三个维度。你可以有一个常规数组的数组,并使用索引 0 表示 x 坐标,索引 1 表示 y 坐标。

在我看来,你正在创建一个完整的第三个维度,其中每个数组的大小为 1,这将更容易将其视为二维数组。虽然它看起来有点像你正在使用数组作为一种键值对,但是索引本身是否可以用作键呢?它们似乎每次都在递增。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接