首页 > 解决方案 > 二维数组转换为一维数组,是完整副本还是对旧内存的另一个引用?

问题描述

那里,

我使用以下代码将二维数组转换(?或者我应该称之为引用?)二维数组到一维数组:

object[] newobj = (object[])obj;

我感到困惑的是,这实际上是分配内存并将完整的“obj”复制到一个新的 1d 数组“newobj”,还是 newobj 只是对“obj”的另一个引用(或者我应该说是指针)?是否需要额外的内存和复制时间?

还有一个问题,如果这个“obj”只是一个变量,而不是一个数组,这段代码会把它转换成一个一维且长度等于1的数组吗?

请用这个澄清我。

在此先感谢,亚历克斯

标签: c#

解决方案


好的,我冒昧地假设您指的是数组数组而不是二维数组,否则该转换将无法编译

多维数组 [][] vs [,]

公平地说,这很令人困惑!

当谈到弄清楚代码是如何工作的时,只要有一个小提琴就永远不会受到伤害。我敲了一些虚拟代码以表明您所做的只是创建对内存的新引用而不是创建副本。

    object[][] obj = new object[5][]; //Delcare Jagged array

    obj[0] = new object[] { 1, 1, 1 };
    obj[1] = new object[] { 2, 2, 2 };
    obj[2] = new object[] { 3, 3, 3 };
    obj[3] = new object[] { 4, 4, 4 };
    obj[4] = new object[] { 5, 5, 5 }; //Fill up with stuff

    Console.WriteLine("{0}", obj[2][0]);  // prints 3

    object[] newobj = (object[])obj; // Declare array of objects and cast 

    newobj[2] = new object[] { 9, 9, 9 }; // update using the new refrence

    Console.WriteLine("{0}", obj[2][0]); // print from old reference, now prints 9
    Console.WriteLine("{0}", ((object[])newobj[2])[0]); // print from new reference, prints 9 but requires a cast
    Console.WriteLine("{0}", newobj[2][0]); // Error, cannot apply indexing with [] to an expression of type object

所以你可以看到从新的一维引用更新数组仍然会更新原始引用仍然指向的底层内存。但是,正如您向编译器坚持的那样,第二个引用是一维数组,您不能再使用 [][] 语法,或者至少不能再次使用强制转换

您还可以使用ILSpy等工具来查看代码是如何编译的。在这种情况下,我们的函数在顶部声明了两个局部类型

.locals init (
    [0] object[][],
    [1] object[]
)

但是当转换发生时,IL 所做的只是将变量 0 的值(引用)压入堆栈并将其弹出到变量 1 中,就这么简单!

IL_00ca: ldloc.0  //push 0
IL_00cb: stloc.1  //pop 1

推荐阅读