86

I have a popuplated IEnumerable<User> collection.

I want to remove an item from it, how can I do this?

foreach(var u in users)
{
  if(u.userId = 1123)
  {
    // remove!
  }
}

I know your not suppose to remove while looping, so I don't mind either creating a new collection or removing it after.

But I don't know how to remove an item, kind of lost for some reason on this!

Alternately which I am confused on also, how can I create a new collection like:

IEnumerable<User> modifiedUsers = new List<User>();

foreach(var u in users)
{
   if(u.userId != 1233)
   {
        modifiedUsers.add ??????
   }
}

How can I add to the collection?

Milad Rashidi
  • 1,296
  • 4
  • 22
  • 40
loyalflow
  • 14,275
  • 27
  • 107
  • 168
  • Btw, while iterating over a list you can not remove elements without getting a runtime error. Like Tilak showed in his answer, the list must be copied prior to enumeration. – henon Nov 22 '21 at 14:55

9 Answers9

81

Not removing but creating a new List without that element with LINQ:

// remove
users = users.Where(u => u.userId != 123).ToList();

// new list
var modified = users.Where(u => u.userId == 123).ToList();
ruffin
  • 16,507
  • 9
  • 88
  • 138
lante
  • 7,192
  • 4
  • 37
  • 57
  • 8
    You are creating a new list in both cases. The first example just overwrites the reference. – Willem D'Haeseleer Oct 17 '16 at 16:08
  • 18
    Your terminology is not correct. You are not removing an item from the list, In both examples you create a new list and the old list remains unaffected. You are merely overwriting the reference in your first example, as such stating that it results in a `remove` is incorrect. You should update your question to clarify that. – Willem D'Haeseleer Oct 18 '16 at 17:43
  • 2
    Clearly the title and author wants to REMOVE the item, not create a new list without it... – Eru Dec 18 '18 at 10:43
  • 1
    Whilst this was useful to me, I just want to point out that the Author asked for removing item from IEnumerable , therefore the suffix ".ToList()" in the examples is not necessary. (Though probably what a lot of people who end up on this page are after.) – egmfrs Jun 13 '19 at 11:12
  • Always use `AsList()` instead of `ToList()` – Alireza Sattari Mar 06 '21 at 01:11
36

You can not remove an item from an IEnumerable; it can only be enumerated, as described here: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx

You have to use an ICollection if you want to add and remove items. Maybe you can try and casting your IEnumerable; this will off course only work if the underlying object implements ICollection`.

See here for more on ICollection: http://msdn.microsoft.com/en-us/library/92t2ye13.aspx

You can, of course, just create a new list from your IEnumerable, as pointed out by lante, but this might be "sub optimal", depending on your actual use case, of course.

ICollection is probably the way to go.

ruffin
  • 16,507
  • 9
  • 88
  • 138
Willem D'Haeseleer
  • 19,661
  • 9
  • 66
  • 99
13

Try turning the IEnumerable into a List. From this point on you will be able to use List's Remove method to remove items.

To pass it as a param to the Remove method using Linq you can get the item by the following methods:

  • users.Single(x => x.userId == 1123)
  • users.First(x => x.userId == 1123)

The code is as follows:

users = users.ToList(); // Get IEnumerable as List

users.Remove(users.First(x => x.userId == 1123)); // Remove item

// Finished
WonderWorker
  • 8,539
  • 4
  • 63
  • 74
dutzu
  • 3,883
  • 13
  • 19
  • but can I assign it to something that expects an ienumerable afterwords? do I have to restart it to the beginning? – loyalflow Jan 03 '13 at 17:03
  • 1
    @user1361315 of course, List implements IEnumerable, so you can indeed assing it to an IEnumerable – dutzu Jan 03 '13 at 17:54
9

You can do something like this:

users = users.Where(x => x.userId != userIdToRemove);
Rafael Mori
  • 821
  • 9
  • 7
3

You can't. IEnumerable<T> can only be iterated.

In your second example, you can remove from original collection by iterating over a copy of it

foreach(var u in users.ToArray()) // ToArray creates a copy
{
   if(u.userId != 1233)
   {
        users.Remove(u);
   }
}
Tilak
  • 30,108
  • 19
  • 83
  • 131
0

The IEnumerable interface is just that, enumerable - it doesn't provide any methods to Add or Remove or modify the list at all.

The interface just provides a way to iterate over some items - most implementations that require enumeration will implement IEnumerable such as List<T>

Why don't you just use your code without the implicit cast to IEnumerable

// Treat this like a list, not an enumerable
List<User> modifiedUsers = new List<User>();

foreach(var u in users)
{
   if(u.userId != 1233)
   {
        // Use List<T>.Add
        modifiedUsers.Add(u);
   }
}
Charleh
  • 13,749
  • 3
  • 37
  • 57
  • I have to modify it, then pass it to something that expects a ienumerable. – loyalflow Jan 03 '13 at 17:04
  • Then modify it and pass it - there is no reason you can't pass a `List` to a method that's expecting an `IEnumerable` since `List` derives from `IEnumerable`. I don't even think you need a cast due to covariance rules. – Charleh Jan 03 '13 at 17:06
0

You can't remove IEnumerable<T> elements, but you can use the Enumerable.Skip Method

spajce
  • 7,044
  • 5
  • 29
  • 44
-1

users.toList().RemoveAll(user => <your condition>)

  • 2
    this will take your whole list into memory due to the .ToList(). This should be avoided at all costs – miThom Sep 14 '21 at 09:22
  • This will only remove the elements from the newly created list, not the original enumerable – mBardos Dec 09 '22 at 10:21
-4

There is now an extension method to convert the IEnumerable<> to a Dictionary<,> which then has a Remove method.

public readonly IEnumerable<User> Users = new User[]; // or however this would be initialized

// To take an item out of the collection
Users.ToDictionary(u => u.Id).Remove(1123);

// To take add an item to the collection
Users.ToList().Add(newuser);
drovani
  • 928
  • 1
  • 17
  • 37