Аргумент Исключение, генерируемое Generic.List при использовании AddRange с пустым Generic.List в качестве аргумента - PullRequest
0 голосов
/ 08 ноября 2019

В моей программе я получаю необработанное System.ArgumentException при попытке использовать функцию AddRange:

Массив назначения был недостаточно длинным. Проверьте destIndex, длину и нижние границы массива.

При отладке я разбиваю исключение в моей строке:

ListA.AddRange(ListB);

В инструменте наблюдения отладчиком я могупосмотрите, что:

ListA: Count = 2454
ListB: Count = 0

Обобщая список документации , ArgumentException не указан.

Я что-то упускаю при попыткеДык, что именно идет не так?

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

List<T> не является поточно-ориентированным. Начиная с документы :

Thread Safety

Открытые статические (Shared в Visual Basic) члены этого типа являются потокобезопасными. Любые члены экземпляра не гарантируют поточнобезопасность.

Безопасно выполнять несколько операций чтения в списке, но могут возникнуть проблемы, если коллекция будет изменена во время чтения. Чтобы обеспечить безопасность потоков, заблокируйте коллекцию во время операции чтения или записи. Чтобы обеспечить доступ к коллекции из нескольких потоков для чтения и записи, необходимо реализовать собственную синхронизацию. Для коллекций со встроенной синхронизацией см. Классы в пространстве имен System.Collections.Concurrent. В качестве альтернативы поточно-ориентированной альтернативе см. Класс ImmutableList.

Это не безопасно для одновременной записи в List<T> из нескольких потоков или для записив List<T> в одном потоке при чтении из него в другом потоке. Вы увидите случайные «необъяснимые» исключения, подобные тому, который вы видите.

Используйте блокировку для правильной синхронизации доступа к вашему списку, используйте поточно-ориентированную коллекцию или реорганизуйте, чтобы вы не делали этогонужно сделать это.

0 голосов
/ 08 ноября 2019

Редактировать: не обращайте внимания на остальную часть моего поста. Это было состояние гонки. Это произошло, по-видимому, во время финальной части AddRange. По-видимому, любой из этих массивов был разного размера во время шага роста и фактического копирования. И до такой степени внутренний массив не вырос достаточно .

A простой блок блокировки , охватывающий всю работу по записи в любом массиве, должен исправить это.

Оригинальный ответ - можно игнорировать

Ваш заголовок объясняет это. Вы получаете исключение аргумента, потому что вы пытаетесь добавить пустой список в существующий список . Это недопустимая операция в соответствии с разработчиками функции AddRange ().

ArgumentException имеет очень узкое назначение:

Исключение, которое выдаетсякогда один из аргументов, предоставленных методу, недопустим.

ArgumentException выдается, когда метод вызывается, и хотя бы один из переданных аргументов не соответствует спецификации параметров вызываемого метода. Свойство ParamName идентифицирует недопустимый аргумент.

Поскольку у него есть эта единственная цель, оно не нуждается в специальном упоминании для каждого случая, когда это может произойти при каждом вызове функции. В самом деле, вы должны столкнуться с тем, чтобы бросить его самостоятельно.

Чтобы избежать этого, не подают пустые списки в AddRange () . Было бы тривиально проверить, что:

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

Поскольку вы предоставили 0 информации о том, как создается ListB, мы не можем сказать вам, почему он иногда пуст в данный момент. Это просто и легко проверяется.

Я использую эти две статьи в качестве основы для обработки исключений:

Это исключение является простым и понятным случаем Boneheaded Exception. Существует удаленный аргумент для пустого списка, который не настолько исключителен. Однако разработчики AddRange () посчитали, что это достаточно исключительный вариант для исключения. Этого также тривиально избегают с помощью базового if, поэтому его нельзя отнести к классу Vexing Exception. Таким образом, даже после всех соображений, это все еще просто исключение. Пожалуйста, прекратите вызывать это.

...