.NET - Удалите из Списка <T> в 'foreach' цикле

В SaveChanges используется SqlCommand. Если имя длиннее, чем ограничение базы данных, оно будет молча усечено, поэтому не будет выдано никакой ошибки.

BulkInsert использует SqlBulkCopy, если имя длиннее, чем предел базы данных, будет выдано сообщение об ошибке.

Это объясняет, почему вы получаете ошибку в одном случае, а не в другом.

SqlBulkCopy не вызывает эту ошибку для развлечения, поэтому я бы дважды проверил вашу длину с вашим размером столбца.

  • Возможно, типом является char(xyz) и в конце есть место?
  • Возможно, в начале есть место?
  • и т. Д.

.NET Fiddle поддерживают пакеты Entity Framework и NuGet. Так что, если бы вы могли воспроизвести это онлайн, можно было бы точно сказать, почему это происходит.

Пример: https://dotnetfiddle.net/35mQ0W

46
задан Peter Mortensen 3 September 2012 в 14:47
поделиться

12 ответов

Вам действительно нужно делать это в цикле foreach ?

Это даст те же результаты, что и ваши примеры, т. Е. Удалит все элементы из списка вверх до первого элемента, который соответствует условию (или удаляю все элементы, если ни один из них не соответствует условию).

int index = Os.FindIndex(x => x.cond);

if (index > 0)
    Os.RemoveRange(0, index);
else if (index == -1)
    Os.Clear();
31
ответ дан 26 November 2019 в 19:58
поделиться

Это хорошо обсуждается в Удаление элементов из списка во время итерации по нему .

Они предлагают:

for(int i = 0; i < count; i++)
{
    int elementToRemove = list.Find(<Predicate to find the element>);

    list.Remove(elementToRemove);
}
1
ответ дан 26 November 2019 в 19:58
поделиться

Если вы знаете, что ваш список не очень большой, вы можете использовать

foreach (Type o in new List<Type>(Os))
    ....

, который создаст временную копию списка. Тогда ваш вызов remove () не будет мешать итератору.

1
ответ дан 26 November 2019 в 19:58
поделиться
 Os.RemoveAll(delegate(int x) { return /// });
9
ответ дан 26 November 2019 в 19:58
поделиться

Обновление: добавлено для полноты картины

Как несколько ответили, вы не следует изменять коллекцию при ее повторении с помощью GetEnumerator () (пример foreach ). Фреймворк не позволяет вам сделать это, создав исключение. Типичным вариантом решения этого является повторение «вручную» с для (см. Другие ответы). Будьте осторожны со своим индексом, чтобы не пропускать элементы или повторно оценивать один и тот же дважды (используя i - или итерацию в обратном направлении).

Однако для вашего конкретного случая мы можем оптимизировать операции удаления ... исходный ответ ниже.


Если вы хотите удалить все элементы, пока один из них не будет соответствовать заданному условию (это то, что делает ваш код), вы можете сделать это:

3
ответ дан 26 November 2019 в 19:58
поделиться

У меня только что возникла проблема с моей библиотекой анализа. Я пробовал это:

for (int i = 0; i < list.Count; i++)
{                
   if (/*condition*/)
   {
       list.RemoveAt(i);
       i--;
   }
}

Это довольно просто, но я не придумал ни одной точки останова.

13
ответ дан 26 November 2019 в 19:58
поделиться

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

Используйте альтернативу while. Это путь.

55
ответ дан 26 November 2019 в 19:58
поделиться

Я программист на Java, но работает что-то вроде этого:

List<Type> Os;
List<Type> Temp;
...
foreach (Type o in Os)
    if (o.cond)
        Temp.add(o);
Os.removeAll(Temp);  
15
ответ дан 26 November 2019 в 19:58
поделиться

Вы можете перебирать список в обратном направлении:

for (int i = myList.Count - 1; i >= 0; i--)
{
    if (whatever) myList.RemoveAt(i);
}

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

58
ответ дан 26 November 2019 в 19:58
поделиться

Я бы попытался найти индекс первого элемента, который не удовлетворяет предикату и сделайте RemoveRange (0, index) на нем. По крайней мере, должно быть меньше вызовов Remove.

4
ответ дан 26 November 2019 в 19:58
поделиться

Посмотрите на Enumerable.SkipWhile ()

Enumerable.SkipWhile( x => condition).ToList()

Обычно отсутствие изменения списка значительно упрощает жизнь. :)

1
ответ дан 26 November 2019 в 19:58
поделиться

Я знаю, что вы просили о чем-то другом, но если вы хотите условно удалить группу элементов, вы можете использовать лямбда-выражение:

Os.RemoveAll(o => !o.cond);
11
ответ дан 26 November 2019 в 19:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: