Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare by reference?

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?

like image 265
haiyyu Avatar asked Feb 14 '12 01:02

haiyyu


2 Answers

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.

like image 176
Austin Salonen Avatar answered Sep 18 '22 06:09

Austin Salonen


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;
}
like image 30
doblak Avatar answered Sep 22 '22 06:09

doblak