Удалить элементы из IEnumerable <T> - PullRequest
45 голосов
/ 06 июля 2010

У меня есть 2 коллекции IEnumerable.

IEnumerable<MyClass> objectsToExcept 

и

IEnumerable<MyClass> allObjects.

objectsToExcept могут содержать объекты allObjects.

, которые необходимо удалитьallObjects объекты в objectsToExcept.Например:

foreach (var myClass in objectsToExcept)
{
allObjects.Remove(myClass);
}

Или

allObject.Except(objectsToExcept)

Но это не работает.Счет после выполнения методов указывает на то, что ни один элемент не был удален.

Ответы [ 5 ]

58 голосов
/ 06 июля 2010

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

Если вы используете результат, например,

IEnumerable<MyClass> others = allObjects.Except(objectsToExcept);
foreach (MyClass x in others)
{
    ...
}

тогда будет хорошо , если вы переопределили GetHashCode и Equals или , если вы счастливы использовать ссылочное равенство. Вы пытаетесь удалить логически равные значения или в обеих последовательностях встречаются одинаковые ссылки ? Вы переопределили GetHashCode и Equals, и если да, уверены ли вы, что эти реализации работают?

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

29 голосов
/ 06 июля 2010

В IEnumerable<T> нет метода Remove, потому что он не предназначен для изменения.

Метод Except не изменяет исходную коллекцию: он возвращает новую коллекцию, которая не содержит исключенные элементы:

var notExcluded = allObjects.Except(objectsToExcept);

См. Except на MSDN .

16 голосов
/ 06 июля 2010

Remove и Except не изменяют исходный IEnumerable.Они возвращают новый.попробуйте

var result = allObject.Except(objectsToexcept);
4 голосов
/ 01 октября 2012

Хотя остальные ответы верны, я должен добавить, что результат вызова Except() может быть возвращен к исходной переменной. То есть

allObjects = allObjects.Except(objectsToExcept);

Также имейте в виду, что Except() будет производить разность наборов двух коллекций, поэтому, если есть дубликаты переменных, которые будут удалены, они будут удалены.

0 голосов
/ 02 мая 2014
others.Where(contract => !objectsToExcept.Any()).ToList();
...