When working with the List class from System.Collections.Generic, methods like Contains or IndexOf will compare the passed reference's object using either the Equals method implemented from IEquatable, or the overridden Equals method provided by the Object class. If Object.Equals is not overridden, it will check whether the passed reference points to the same object as itself.
My question is: Is there a way of making List compare by reference if Equals is overridden? The code below will remove the item from the list:
class Program
{
static void Main(string[] args)
{
var s1 = new SomeClass() { A = 5 };
var s2 = new SomeClass() { A = 5 };
var list = new List<SomeClass>();
list.Add(s1);
list.Remove(s2); // s1 will get removed, even though s2 has been
// passed, because s1's Equals method will return true.
}
}
class SomeClass
{
public int A { get; set; }
public override bool Equals(object obj)
{
SomeClass s = obj as SomeClass;
if (s == null)
{
return false;
}
else
{
return s.A == this.A;
}
}
}
Let's say I'm unable to remove SomeClass' implementation of Equals, is there a way of making List compare by reference instead of value?
You can use List.RemoveAll and in your predicate, compare the items with Object.ReferenceEquals.
list.RemoveAll(item => object.ReferenceEquals(item, s2));
The code did successfully remove the 1 items when debugging from Visual Studio 2010 Express.
Austin's solution is simple and work. But here are two generic extension methods as well:
items.RemoveAllByReference(item);
public static void RemoveAllByReference<T>(this List<T> list, T item)
{
list.RemoveAll(x=> object.ReferenceEquals(x, item));
}
public static bool RemoveFirstByReference<T>(this List<T> list, T item)
{
var index = -1;
for(int i = 0; i< list.Count; i++)
if(object.ReferenceEquals(list[i], item))
{
index = i;
break;
}
if(index == -1)
return false;
list.RemoveAt(index);
return true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With