【问题标题】:C# 3 dimensional array definition issueC# 3维数组定义问题
【发布时间】:2009-03-29 11:41:04
【问题描述】:

我下面的代码有编译错误,

错误 1 ​​无法将类型 'TestArray1.Foo[,,*]' 隐式转换为 'TestArray1.Foo[][][]' C:\Users\lma\Documents\Visual Studio 2008 \Projects\TestArray1\TestArray1\Program.cs 17 30 TestArray1

有人有什么想法吗?这是我的全部代码,我使用的是 VSTS 2008 + Vista 64 位。

namespace TestArray1
{
    class Foo
    {    
    }

    class Program
    {
        static void Main(string[] args)
        {
            Foo[][][] foos = new Foo[1, 1, 1];

            return;
        }
    }
}

编辑:版本 2。我有另一个版本的代码,但仍然有编译错误。有什么想法吗?

Error   1   Invalid rank specifier: expected ',' or ']' C:\Users\lma\Documents\Visual Studio 2008\Projects\TestArray1\TestArray1\Program.cs 17  41  TestArray1
Error   2   Invalid rank specifier: expected ',' or ']' C:\Users\lma\Documents\Visual Studio 2008\Projects\TestArray1\TestArray1\Program.cs 17  44  TestArray1


namespace TestArray1
{
    class Foo
    {    
    }

    class Program
    {
        static void Main(string[] args)
        {
            Foo[][][] foos = new Foo[1][1][1];

            return;
        }
    }
}

编辑:版本 3。我想我想要一个锯齿状数组。并在向其他人学习之后。这是我的代码修复,它在 VSTS 2008 中编译得很好。我想要的是一个锯齿状数组,目前我只需要一个元素。谁能检查我的代码是否正确以实现我的目标?

namespace TestArray1
{
    class Foo
    {    
    }

    class Program
    {
        static void Main(string[] args)
        {
            Foo[][][] foos = new Foo[1][][];
            foos[0] = new Foo[1][];
            foos[0][0] = new Foo[1];
            foos[0][0][0] = new Foo();
            return;
        }
    }
}

提前致谢, 乔治

【问题讨论】:

  • 第 3 版看起来不错,但不得不怀疑 size=1 的事情。您确实意识到 foos 只是 int foos 的复杂版本; ?
  • @Henk,其实数组定义是xsd工具自动生成的C#文件。
  • 好的,但是你可能想在返回之前再添加 1 行:foos[0][0][0] = new Foo();
  • @Henk,非常感谢!为了这个讨论线程的完整性,我添加了这一行。 :-)
  • 是的,这就是你想要的。不过,return 语句是多余的。

标签: c# arrays


【解决方案1】:

关于您的代码的第 2 版 - 不幸的是,您不能以这种方式指定锯齿状数组。相反,您需要这样做:

Foo[][][] foos = new Foo[1][][];
foos[0] = new Foo[1][];
foos[0][0] = new Foo[1];

基本上,您必须分别填充每个数组。 Foo[][][] 表示“Foo 数组的数组”。像这样的初始化语句一次只能初始化 一个 数组。使用矩形数组,您最终仍然只有一个(多维)数组,这就是 new Foo[1,1,1] 有效的原因。

顺便说一句,如果这是针对真正的代码,我会敦促您至少考虑其他设计决策。数组数组可能很有用,但您很容易遇到这样的问题。数组数组的数组甚至更糟糕。可能有更易读的方式来表达您感兴趣的内容。

【讨论】:

  • @Jon,我已按照您的 cmets 添加了我的代码的第 3 版。您能否帮助检查我的代码是否正确以实现我的目标?谢谢!
  • @Jon,你的建议很有帮助。实际上数组定义来自xsd工具自动生成的C#文件。 :-(
  • @George2:对这个问题发表了评论。可惜它是自动生成的代码。你可能想在它周围放置一个更易读的外观。
  • 谢谢乔恩,下次我会注意的。开发人员有时很懒惰。 :-)
  • @Jon,我了解到由于 GetLength 边界检查,多维数组似乎比锯齿数组慢?我很困惑,我认为锯齿状数组也需要这样的边界检查,为什么锯齿状数组更快?
【解决方案2】:

下定决心:)

你要么想要:

Foo[,,] foos = new Foo[1, 1, 1];

或:

Foo[][][] foos = new Foo[1][1][1];

【讨论】:

  • 嗨 Jon,将 foos 定义为 [,,] 或 [][][] 有什么区别?我觉得他们是一样的! :-)
  • 第二个是锯齿状的,这意味着对于每一行,下一个维度可以有不同大小的数组。
  • 第一个是一个三维数组,即一个连续的内存块保存所有元素。另一种语法是数组数组的数组,它具有非常糟糕的内存局部性,此外,单个数组的大小也可以不同。这完全取决于你想要什么
  • @Jon/@aaronls/@Johannes,我已经关注了你的 cmets,但仍然有编译错误。请在我的原始帖子中检查我的代码版本 2 以了解我的新代码和编译错误。有什么想法或cmets?
  • new Foo[1][1][1] 无效。您必须执行 new Foo[1][][] 然后填充每个子数组。
【解决方案3】:

您正在声明一个双嵌套数组(array of array of array)并分配一个三维数组。这两个肯定是不一样的。您可以将您的声明更改为

Foo[,,] foos = new Foo[1,1,1]

如果你想要一个真正的三维数组。锯齿状数组([][][] 类型)在 C# 中不像在 Java 中那样需要。

【讨论】:

  • @Johannes,让我们让事情变得更简单,比如将维度从 3 更改为 2,那么嵌套数组和二维数组有什么区别? :-)
  • Jon Skeet 对此有一个很好的回答。基本上,n 维数组就是:一个具有 n 维的单个数组。而 [][] 变体是一个数组数组,即数组的每个元素本身就是一个数组,这在很少需要支持第一种类型的语言中。
  • @Johannes,谢谢!我了解到,由于 GetLength 边界检查,多维数组似乎比锯齿状数组慢?我很困惑,我认为锯齿状数组也需要这样的边界检查,为什么锯齿状数组更快?
  • 嗯,很有趣。不知道那个。无论如何:如果您认为性能是一个问题,请对其进行分析。试一试,找出瓶颈在哪里。如果边界检查有问题,您总是可以将其包装在未经检查的块中。
  • @Johannes,我认为这不是问题。我只是在技术上对为什么感兴趣。有什么想法吗?
【解决方案4】:

最简单的答案是使用

Foo[,,] foos = new Foo[2, 3, 4];

这为您提供了一个 3 维数组作为 2*3*4=24 Foo 的连续内存块。

替代方案看起来像:

Foo[][][] foos = new Foo[2][][];

for (int a = 0; a < foos.Length; a++)
{
  foos[a] = new Foo[3][];
  for (int b = 0; b < foos[a].Length; b++)
  {
     foos[a][b] = new Foo [4];

     for (int c = 0; c < foos[a][b].Length; c++)
        foos[a][b][c] = new Foo();
  }
}

虽然这种锯齿状(= 数组数组)方法工作量更大,但使用它实际上更快。这是由编译器的一个缺点引起的,它在访问 Foo[,,] 情况下的元素时总是会进行范围检查,而它至少能够优化使用 Foo[] 中的 Length 属性的 for 循环[][] 设想。

另见this question

【讨论】:

  • @George2:我解释了一下,加了个链接
  • @Henk,我已按照您的 cmets 添加了我的代码的第 3 版。您能否帮助检查我的代码是否正确以实现我的目标?谢谢!
  • @Henk,我阅读了您推荐的问题 2 小时。由于 GetLength 边界检查,多维数组似乎很慢?我很困惑,我认为锯齿状数组也需要这样的边界检查,为什么锯齿状数组更快?
  • @George2,(JIT?) 编译器在识别 i
  • @Henk,您认为哪个 JITed 指令不好导致多维数组比锯齿数组慢?请您引用以使其更清楚吗?
【解决方案5】:

这两个不同的数组声明创建了非常不同的东西。

让我们看看更简单的情况:

Foo[,] twoDimensionArray = new Foo[5,5];

这个数组有两个维度——你可以把它想象成一个表格。您需要两个轴才能返回任何内容:

Foo item = twoDimensionArray[2,3]

索引始终具有相同的长度 - 在本例中为 0-4。

锯齿状数组实际上是数组的数组:

Foo[][] jaggedArray = new Foo[5][];

jaggedArray[0] = new Foo[2];
jaggedArray[1] = new Foo[4];
...

如果你只使用一个轴索引,它将返回一个数组:

Foo[] oneRow = jaggedArray[3];

如果您同时使用两者,则从子数组中进行选择:

Foo item = jaggedArray[3][2];

//would be the same as:
Foo item = oneRow[2];

每个子数组都可以有不同的长度,甚至不被填充。

【讨论】:

  • @Keith,“甚至没有被填充”是什么意思?换个说法?
  • 我已按照您的 cmets 添加了我的代码的第 3 版。您能否帮助检查我的代码是否正确以实现我的目标?谢谢!
  • “不被填充”我的意思是子数组可以为空——当你初始化它时。
【解决方案6】:

取决于您是否希望它们呈锯齿状:

//makes a 5 by 4 by 3 array:

string[,,] foos = new string[5,4,3];

http://msdn.microsoft.com/en-us/library/aa288453(VS.71).aspx

哦,这里是初始化值:

    char[, ,] blah = new char[2, 2, 2] { 
        {{ '1', '2' }, { '3', '4' }},
        {{ '5', '6' }, { '7', '8' }}
         };

请注意,这不起作用:

Foo[][][] foos = new Foo[1][1][1];

因为您使用的是交错数组语法,它不允许您定义嵌套数组的大小。而是使用这样做:

Foo[,,] foos = new Foo[1][1][1];  //1 by 1 by 1

或者这个

Foo[][][] foos = new Foo[1][][];  //1 array allowing two nested levels of jagged arrays
foos[0] = new Foo[1];  //for the first element, create a new array nested in it
foos[0][0] = new Foo[1]; //create a third level new array nested in it

【讨论】:

  • 嗨 aaronls,我想要一个三维数组。我试过了,但仍然有编译错误。请在我的原始帖子中检查我的代码版本 2 以了解我的新代码和编译错误。有什么想法或cmets?
  • @aaronls,我已按照您的 cmets 添加了我的代码的第 3 版。您能否帮助检查我的代码是否正确以实现我的目标?谢谢!
  • 版本 3 看起来正确,但请注意它只能保存一个值。
【解决方案7】:

如果它有任何意义,仅用于 C# 声明:

int[,,] ary = new int[,,]
{
      { { 111, 112 }, { 121, 122 }, { 131, 132 } } 
    , { { 211, 212 }, { 221, 222 }, { 231, 232 } } 
    , { { 311, 312 }, { 321, 322 }, { 331, 332 } } 
    , { { 411, 412 }, { 421, 422 }, { 431, 432 } } 
};

【讨论】:

    【解决方案8】:

    数组初始化

    int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } }, 
                                    { { 7, 8, 9 }, { 10, 11, 12 } } }
    

    来源:Multidimensional Arrays (C# Programming Guide)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-27
      • 1970-01-01
      • 1970-01-01
      • 2018-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多