Сравнить по ссылке? - PullRequest
       7

Сравнить по ссылке?

10 голосов
/ 14 февраля 2012

При работе с классом List из System.Collections.Generic такие методы, как Contains или IndexOf, будут сравнивать объект переданной ссылки, используя либо метод Equals, реализованный из IEquatable, либо переопределенный метод Equals, предоставляемый классом Object. Если Object.Equals не переопределен, он проверит, указывает ли переданная ссылка на тот же объект, что и он сам.

Мой вопрос таков: есть ли способ сделать List сравниваемым по ссылке, если равно Equals? Код ниже удалит элемент из списка:

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

Допустим, я не могу удалить реализацию Equals для SomeClass, есть ли способ сделать сравнение List по ссылке вместо значения?

Ответы [ 2 ]

14 голосов
/ 14 февраля 2012

Вы можете использовать List.RemoveAll и в своем предикате сравнить элементы с Object.ReferenceEquals .

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

Код успешно удалил 1элементы при отладке из Visual Studio 2010 Express.

4 голосов
/ 14 февраля 2012

Решение Остина простое и удобное. Но вот два общих метода расширения:

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