使用System.Collections.Generic中的List类时,Contains或IndexOf等方法将使用IEquatable实现的Equals方法或Object类提供的重写Equals方法来比较传递的引用对象。如果未覆盖Object.Equals,它将检查传递的引用是否指向与其自身相同的对象。
我的问题是:如果等于被覆盖,是否有一种方法可以通过引用进行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;
}
}
}
假设我无法删除SomeClass的Equals实现,有没有办法通过引用而不是值来进行List比较?
答案 0 :(得分:14)
您可以使用List.RemoveAll并在谓词中将项目与Object.ReferenceEquals进行比较。
list.RemoveAll(item => object.ReferenceEquals(item, s2));
从Visual Studio 2010 Express调试时,代码成功删除了1个项目。
答案 1 :(得分:4)
奥斯汀的解决方案很简单,也很有效。但是这里有两种通用的扩展方法:
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;
}