为什么可以';t将项添加到循环中的数组中
本文关键字:添加 循环 数组 为什么 | 更新日期: 2023-09-27 18:21:34
为什么在C#中,除非声明数组的长度或直接添加项,否则不能向数组添加对象?例如,我不能简单地做这个
foreach(object item in array)
{
array.Add(item)
}
我必须创建一个列表,并在循环后将其转换为数组。
我不想知道怎么做,我想有一个逻辑解释为什么数组是固定长度的,但其他集合不是(List,ListArray)
原始答案(在编辑答案之前):
因为foreach循环不会动态更改其结束条件,所以在动态更改它迭代的对象时。
在您的情况下(如果可能的话),它永远不会结束,因为在每个循环中都有一个项被添加到数组中。
你可以使用一个正常的for循环:
int orgSize = array.Count
for (var i = 0; i < orgSize; i++)
{
array.Add(array[i])
}
更新问题的答案:为什么数组是固定长度的,但其他集合不是(List,ListArray):
数组是固定长度的,可能是由于历史原因以及与C/C++保持向后兼容性。这些"普通"数组没有Add、Count,也不是动态的。因此,使用List/ListArray等要容易得多,尽管这会带来成本,比如可能需要一些性能,而且在所有情况下都需要更多的存储,因为需要对实例化进行管理。然而,如果这不是一个问题,我更喜欢使用List/ListArray/Dictionary类型,因为它的可用性/功能得到了改进。
数组不可调整大小,因为内存就是这样工作的。了解内存分配在.NET中的确切工作方式有点难。因此,如果你愿意,你可以在其他地方阅读有关它的全部内容,但有一个方面基本上在每个平台上都是通用的:当你有一块内存分配给某个东西时,之后的下一个地址可能是其他东西的一部分。
因此,你不能只是扩展一块内存,希望没有任何问题,你必须测试你是否可以扩展它,并在不能扩展的时候制定一个B计划——B计划将分配一个新的内存块,将旧的东西复制到其中,并释放旧的块。
为了避免多次重新分配和复制,通常的做法是使新块是旧块的两倍大,因此如果添加n
项,则只会重新分配&复制O(log n)
次,将向动态增长的数组中添加新项的摊销时间降到O(1)。如此恒定的时间,太棒了——不是真的。与不需要重新分配相比,这仍然需要更多的时间,事实上,即使没有导致增长的每个add
都有一点开销来确保还没有必要增长。
因此,不增长的阵列要简单得多,速度要快一点,并且浪费的内存更少。因此,在C#(以及许多其他语言,如Java和C++)中,您可以选择:您想使用可增长的"类似数组的东西"还是不可增长的?这是一种权衡,这些语言选择不为你做这个决定。
因为
数组的长度从声明时起是固定的,您既不能添加也不能删除项。您可以创建一个长度更大的新数组,并从一个数组复制到另一个数组,但不能动态更改数组的长度。您可能需要
List<>
或其他集合类型。当你迭代任何集合(List、Dictionay、ArrayList等)时,你不能更改它,这是语言/库设计者设置的限制。允许它将涉及大量的工作,并且会对性能产生影响,这将阻碍每个foreach循环的性能,而不仅仅是在迭代时更改集合的循环。
所以tl;你不能,因为这就是的设计方式
希望这能有所帮助。
您也可以走老式的路线,使用for循环。这不知道迭代器和集合更改问题,也不需要临时列表之类的东西(似乎效率很低)。
数组具有固定长度。但是,如果您事先知道所需的大小,则可以使用循环来填充它们:
var sourceArray = new string[100];
/* populate source */
var myArray = new string[sourceArray.Length];
for (var i = 0; i < sourceArray.Length; i++)
{
myArray[i] = sourceArray[i];
}
实际上,您的问题不清楚,或者说没有什么意义。如果你试图填充一个现有的数组(有一个定义的大小,但没有值),你可以这样做:
var myArray = new string[5];
for(var i = 0; i < myArray.Length; i++)
{
myArray[i] = "Some value here...";
}
然而,将现有项添加到数组本身毫无意义。
注意:Add()
方法存在于List
等,但在那里,它通常意味着"将此元素附加到我的集合的末尾"。
数组具有已定义的长度,该长度不能更改,因此不能向其追加,只能更改现有元素。