我可以保证非 ref 方法不会改变 C# 数组大小吗?

5

参见:

这两个问题不同之处在于它们问的是如何更改大小,我很清楚答案是:“不要使用列表”。它们还引用了一个基于 ref 的 Array.Resize(ref array, int size)

我的问题是:

假设我有一个庞大的遗留代码库,我不可能检查全部内容,并且不能保证它所做的事情。如果我调用一个非按引用传递的数组方法,那么我可以保证数组大小不会改变吗?

Array.Resize 不是问题,因为按引用传递必须通过调用堆栈一直传递,显然不会这样。

但是还有其他可能的问题吗?

关于不是重复的说明

我认为这是一个不同的问题,因为这是一个“是否可能?”而不是“我该如何做/最好的方法是什么”。因此,对于我的问题来说,那些邪恶和错误的答案仍然是相关的。


是的,数组不会改变。它可以。而且当通过引用传递时,您的数组也不会改变,您只会得到另一个具有不同大小的数组。 - Sergey.quixoticaxis.Ivanov
2个回答

20

我可以保证数组大小之后不会改变吗?

可以,因为数组大小永远不会改变。使用Array.Resize方法会创建一个新的数组并将数据复制到其中;它实际上并没有真正地调整原有数组的大小。如果您拥有旧数组的引用,那么:您可以放心,数组大小不会改变。


1

这个数组的大小是不可变的。

  1. 托管数组在大小上永远不会改变:

C#中的数组是“托管数组”,由GC在托管堆上分配。在Managed C++中,您需要编写[1]

array<N*>^ arr = gcnew array<N*>(3);

这是从托管堆的角度看一个单一的原子对象,它不能被调整大小,只能被使用并最终进行垃圾回收。在托管C++中[2]没有gcresizegc-re-new操作符,因为这在CLR中是禁止的。如果托管对象在其生命周期内可以改变大小,那么托管GC将会显著复杂化。我没有找到这个断言的权威文档引用,但我相信这是正确的。
你可能会问"Array.Resize"方法是如何工作的,如果数组从不改变大小。正如文档所解释的那样:

此方法使用指定的大小分配一个新数组,将元素从旧数组复制到新数组,然后用新数组替换旧数组。

Array.Resize方法然后更新数组类型变量以指向新数组(因为变量是按引用传递的),并允许旧数组被GC'ed(除非有另一个引用它)。
  1. C#中的方法参数是按值传递的

...因此,如果您没有使用其他按引用传递的方法,那么没有人可以更新您的数组类型变量以指向不同的数组。

我相信1和2的结合已经回答了您的问题。

这与List有何不同?

List可以在不使用按引用传递的方法的情况下改变大小。这有点不同。List对象本身位于托管堆上,大小永远不会改变,但它包含一个指向数组的指针作为成员变量。当List增长时,该指针将被更新,以指向包含新元素的更长的数组。


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