使用空 Generic.List 作为参数的 AddRange 时 Generic.List 引发的参数异常

Argument Exception thrown by Generic.List when using AddRange with an empty Generic.List as argument

在我的程序中,我在尝试使用 AddRange 函数时遇到未处理的 System.ArgumentException

Destination Array was not long enough. Check destIndex and length, and the array's lower bounds.

调试时,我中断了我所在行的异常:

ListA.AddRange(ListB);

在调试器的监视工具中我可以看到:

ListA: Count = 2454
ListB: Count = 0

查看 documentation 的通用列表,未列出 ArgumentException

我在试图查明到底出了什么问题时是否遗漏了什么?

编辑:别管我 post 的其余部分了。这是一个竞争条件。这显然发生在最后的 AddRange 部分。显然,在增长步骤和实际副本中,任一数组的大小都不同。到这样的程度,内部阵列还没有增长足够

一个 simple lock block 涵盖了任一阵列上的所有写作工作应该可以解决这个问题。

原答案-可以忽略

您的标题说明了这一点。您得到一个参数异常,因为您试图将一个空列表添加到现有列表。根据 AddRange() 函数的设计者,这不是有效操作。

ArgumentException 的用途非常狭窄:

The exception that is thrown when one of the arguments provided to a method is not valid.

ArgumentException is thrown when a method is invoked and at least one of the passed arguments does not meet the parameter specification of the called method. The ParamName property identifies the invalid argument.

因为它只有一个目的,所以不需要特别提及它可能在每个函数调用中发生的每种情况。确实应该鼓励你自己扔。

为避免这种情况,不要将空列表输入 AddRange()。检查以下内容将是微不足道的:

if(ListB.Lent > 0){
  ListA.AddRange(ListB);
}

由于您提供了 0 条有关如何创建 ListB 的信息,我们现在无法告诉您为什么它有时是空的。它就是这样,而且很容易检查。

我使用这两篇​​文章作为我的异常处理的基础:

这个异常是一个简单明了的 Boneheaded 异常。有一个空列表不是那么异常的远程参数。然而,AddRange() 的设计者认为它非常出色,足以保证例外。它也被基本的 if 简单地避免了,所以它不能真正被归类为 Vexing Exception。所以就算是想来想去,也终究只是一个笨蛋的例外。请停止造成它。

List<T> 不是线程安全的。来自 the docs:

Thread Safety

Public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

It is safe to perform multiple read operations on a List, but issues can occur if the collection is modified while it's being read. To ensure thread safety, lock the collection during a read or write operation. To enable a collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization. For collections with built-in synchronization, see the classes in the System.Collections.Concurrent namespace. For an inherently thread-safe alternative, see the ImmutableList class.

从多个线程同时写入 List<T> 或在一个线程上同时写入 List<T> 安全在另一个线程上读取它。您会看到随机的“无法解释的”异常,就像您现在看到的那样。

使用锁来正确同步对列表的访问,使用线程安全的集合,或者重新架构,这样您就不需要这样做了。