如何以及何时放弃在 C# 中使用数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/75976/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 11:14:35  来源:igfitidea点击:

How and when to abandon the use of arrays in C#?

提问by Keng

I've always been told that adding an element to an array happens like this:

我一直被告知向数组添加元素是这样发生的:

An empty copy of the array+1element is created and then the data from the original array is copied into it then the new data for the new element is then loaded

创建数组+1元素的空副本,然后将原始数组中的数据复制到其中,然后加载新元素的新数据

If this is true, then using an array within a scenario that requires a lot of element activity is contra-indicated due to memory and CPU utilization, correct?

如果这是真的,那么由于内存和 CPU 利用率,在需要大量元素活动的场景中使用数组是禁忌的,对吗?

If that is the case, shouldn't you try to avoid using an array as much as possible when you will be adding a lot of elements? Should you use iStringMap instead? If so, what happens if you need more than two dimensions AND need to add a lot of element additions. Do you just take the performance hit or is there something else that should be used?

如果是这种情况,当您将添加大量元素时,您是否应该尽量避免使用数组?你应该改用 iStringMap 吗?如果是这样,如果您需要两个以上的维度并且需要添加大量元素,会发生什么情况。您是否只是在性能上受到影响,还是应该使用其他东西?

采纳答案by Joel Coehoorn

Look at the generic List<T>as a replacement for arrays. They support most of the same things arrays do, including allocating an initial storage size if you want.

将泛型List<T>视为数组的替代品。它们支持数组所做的大部分事情,包括根据需要分配初始存储大小。

回答by Abe Heidebrecht

When the array is resized, a new array must be allocated, and the contents copied. If you are only modifying the contents of the array, it is just a memory assignment.

调整数组大小时,必须分配一个新数组,并复制内容。如果只是修改数组的内容,那只是内存分配。

So, you should not use arrays when you don't know the size of the array, or the size is likely to change. However, if you have a fixed length array, they are an easy way of retrieving elements by index.

因此,当您不知道数组的大小时,不应使用数组,否则大小可能会发生变化。但是,如果您有一个固定长度的数组,它们是一种通过索引检索元素的简单方法。

回答by Jon

The best thing you can do is to allocate as much memory as you need upfront if possible. This will prevent .NETfrom having to make additional calls to get memory on the heap. Failing that then it makes sense to allocate in chunks of five or whatever number makes sense for your application.

如果可能,您可以做的最好的事情是预先分配尽可能多的内存。这将防止.NET必须进行额外的调用来获取堆上的内存。如果失败,那么以五个或任何对您的应用程序有意义的数字为单位进行分配是有意义的。

This is a rule you can apply to anything really.

这是一条您可以真正应用于任何事物的规则。

回答by user13288

A standard array should be defined with a length, which reserves all of the memory that it needs in a contiguous block. Adding an item to the array would put it inside of the block of already reserved memory.

标准数组应该定义一个长度,它在一个连续块中保留它需要的所有内存。向数组中添加一个项目会将它放在已经保留的内存块中。

回答by Jonathan Rupp

In general, I prefer to avoid array usage. Just use List<T>. It uses a dynamically-sized array internally, and is fast enough for most usage. If you're using multi-dimentional arrays, use List<List<List<T>>> if you have to. It's not that much worse in terms of memory, and is much simpler to add items to.

一般来说,我更喜欢避免使用数组。只需使用 List<T>。它在内部使用动态大小的数组,并且对于大多数用途来说足够快。如果您使用的是多维数组,请在必要时使用 List<List<List<T>>>。就内存而言,它并没有那么糟糕,并且添加项目要简单得多。

If you're in the 0.1% of usage that requires extreme speed, make sure it's your list accesses that are really the problem before you try to optimize it.

如果您在 0.1% 的使用率中需要极快的速度,请在尝试优化之前确保列表访问确实是问题所在。

回答by Tom Ritter

ArrayList and List grow the array by more than one when needed (I think it's by doubling the size, but I haven't checked the source). They are generally the best choice when you are building a dynamically sized array.

ArrayList 和 List 在需要时将数组增加一倍以上(我认为这是通过将大小增加一倍,但我还没有检查来源)。当您构建动态大小的数组时,它们通常是最佳选择。

When your benchmarks indicate that array resize is seriously slowing down your application (remember - premature optimization is the root of all evil), you can evaluate writing a custom array class with tweaked resizing behavior.

当您的基准测试表明数组调整大小严重拖慢您的应用程序时(请记住 - 过早优化是万恶之源),您可以评估编写具有调整调整大小行为的自定义数组类。

回答by Greg Hurlman

Arrays are great for few writes and many reads, particularly those of an iterative nature - for anything else, use one of the many other data structures.

数组非常适合少量写入和大量读取,特别是那些具有迭代性质的 - 对于其他任何事情,请使用许多其他数据结构之一。

回答by apenwarr

If you're going to be adding/removing elements a lot, just use a List. If it's multidimensional, you can always use a List<List<int>> or something.

如果您要大量添加/删除元素,只需使用列表。如果它是多维的,你总是可以使用 List<List<int>> 或其他东西。

On the other hand, lists are less efficient than arrays if what you're mostly doing is traversingthe list, because arrays are all in one place in your CPU cache, where objects in a list are scattered all over the place.

另一方面,如果您主要做的是遍历列表,则列表的效率低于数组,因为数组都位于 CPU 缓存中的一个位置,而列表中的对象则分散在各处。

If you want to use an array for efficient reading but you're going to be "adding" elements frequently, you have two main options:

如果您想使用数组进行高效读取,但又要频繁地“添加”元素,您有两个主要选择:

1) Generate it as a List (or List of Lists) and then use ToArray() to turn it into an efficient array structure.

1) 将其生成为List(或List of Lists),然后使用ToArray() 将其变成高效的数组结构。

2) Allocate the array to be larger than you need, then put the objects into the pre-allocated cells. If you end up needing even more elements than you pre-allocated, you can just reallocate the array when it fills, doubling the size each time. This gives O(log n) resizing performance instead of O(n) like it would be with a reallocate-once-per-add array. Note that this is pretty much how StringBuilder works, giving you a faster way to continually append to a string.

2) 分配比您需要的更大的数组,然后将对象放入预先分配的单元格中。如果您最终需要比预先分配的元素更多的元素,您可以在数组填满时重新分配数组,每次将大小加倍。这提供了 O(log n) 调整大小的性能,而不是 O(n),就像使用 relocate-once-per-add 数组一样。请注意,这几乎是 StringBuilder 的工作方式,为您提供了一种更快的方法来不断地附加到字符串。

回答by Sam

You are correct an array is great for look ups. However modifications to the size of the array are costly.

你是对的,数组非常适合查找。然而,对数组大小的修改代价高昂。

You should use a container that supports incremental size adjustments in the scenario where you're modifying the size of the array. You could use an ArrayList which allows you to set the initial size, and you could continually check the size versus the capacity and then increment the capacity by a large chunk to limit the number of resizes.

在修改数组大小的情况下,您应该使用支持增量大小调整的容器。您可以使用允许您设置初始大小的 ArrayList,并且您可以不断检查大小与容量,然后将容量增加一大块以限制调整大小的次数。

Or you could just use a linked list. Then however look ups are slow...

或者你可以只使用一个链表。然而,查找速度很慢......

回答by Alex Lyman

This really depends on what you mean by "add."

这实际上取决于您所说的“添加”是什么意思。

If you mean:

如果你的意思是:

T[] array;
int i;
T value;
...
if (i >= 0 && i <= array.Length)
    array[i] = value;

Then, no, this does not create a new array, and is in-fact the fastest way to alter any kind of IList in .NET.

然后,不,这不会创建一个新数组,而且实际上是更改 .NET 中任何类型的 IList 的最快方法。

If, however, you're using something like ArrayList, List, Collection, etc. then calling the "Add" method maycreate a new array -- but they are smart about it, they don't just resize by 1 element, they grow geometrically, so if you're adding lots of values only every once in a while will it have to allocate a new array. Even then, you can use the "Capacity" property to force it to grow before hand, if you know how many elements you're adding (list.Capacity += numberOfAddedElements)

但是,如果您使用的是 ArrayList、List、Collection 等,那么调用“Add”方法可能会创建一个新数组——但他们很聪明,他们不只是调整 1 个元素的大小,他们几何增长,所以如果你只是每隔一段时间添加很多值,它就必须分配一个新数组。即便如此,如果您知道要添加的元素数量 ( list.Capacity += numberOfAddedElements)