Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List<List<int>> Remove() method

Tags:

c#

list

I'd like to use Remove() method on list of lists, but it's not working for me.
Simple example should say everything:

List<List<int>> list = new List<List<int>>();
list.Add(new List<int> { 0, 1, 2 });
list.Add(new List<int> { 1, 2 });
list.Add(new List<int> { 4 });
list.Add(new List<int> { 0, 1, });

list.Remove(new List<int> { 1, 2 });

If I use RemoveAt(1) it works fine but Remove() not.
It is obviously the same reason that this code returns false:

List<int> l1 = new List<int>();
List<int> l2 = new List<int>();
l1.Add(1);
l2.Add(1);

bool b1 = l1 == l2; // returns False
bool b2 = l1.Equals(l2); // returns False too

So it seems to me that I cannot simply compare two lists or even arrays. I can use loops instead of Remove(), but there must be easier way.

Thanks in advance.

like image 450
cozzy Avatar asked Nov 28 '22 10:11

cozzy


1 Answers

The problem is that List<T> doesn't override Equals and GetHashCode, which is what List<T> will use when trying to find an item. (In fact, it will use the default equality comparer, which means it'll use the IEquatable<T> implementation if the object implements it, and fall back to object.Equals/GetHashCode if necessary). Equals will return false as you're trying to remove a different object, and the default implementation is to just compare references.

Basically you'd have write a method to compare two lists for equality, and use that to find the index of the entry you want to remove. Then you'd remove by index (using RemoveAt). EDIT: As noted, Enumerable.SequenceEqual can be used to compare lists. This isn't as efficient as it might be, due to not initially checking whether the counts are equal when they can be easily computed. Also, if you only need to compare List<int> values, you can avoid the virtual method call to an equality comparer.

Another alternative is to avoid using a List<List<int>> in the first place - use a List<SomeCustomType> where SomeCustomType includes a List<int>. You can then implement IEquatable<T> in that type. Note that this may well also allow you to encapsulate appropriate logic in the custom type too. I often find that by the type you've got "nested" collection types, a custom type encapsulates the meaning of the inner collection more effectively.

like image 144
Jon Skeet Avatar answered Dec 05 '22 13:12

Jon Skeet