参照比较

本文关键字:比较 | 更新日期: 2023-09-27 18:24:17

使用System.Collections.Generic中的List类时,Contains或IndexOf等方法将使用从IEquatable实现的Equals方法或object类提供的重写Equals法来比较传递的引用的对象。如果Object.Equals未被重写,它将检查传递的引用是否指向与其自身相同的对象。

我的问题是:如果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?

参照比较

您可以使用List.RemoveAll,并在谓词中,将项与Object.ReferenceEquals进行比较。

list.RemoveAll(item => object.ReferenceEquals(item, s2));

从Visual Studio 2010学习版调试时,代码成功删除了1项。

Austin的解决方案简单有效。但这里也有两种通用的扩展方法:

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;
}