views:

235

answers:

3

LinkedList.Contains method. (.NET 2)

How the objects are compared inside? (Equals? CompareTo?)

MSDN tells nothing about.

the situation:

interface IClass
{
    string GetName();
}

class Class1 : IClass, IEquatable<Class1>
{
    public string FirstName;
    public string LastName;

    string IClass.GetName() { return FirstName; }

    bool IEquatable<Class1>.Equals(Class1 other)
    {
     return FirstName.Equals(other.FirstName);
    }
}

class Class2 : IClass, IEquatable<Class2>
{
    public string FirstName;
    public string LastName;

    string IClass.GetName() { return LastName; }

    bool IEquatable<Class2>.Equals(Class2 other)
    {
     return LastName.Equals(other.LastName);
    }
}

public void TestMethod() 
{
    Class1 c1 = new Class1();
    c1.FirstName = "fn";
    c1.FirstName = "ln";

    Class2 c2 = new Class2();
    c2.FirstName = "fn";
    c2.FirstName = "ln";

    Class1 c3 = new Class1();
    c3.FirstName = "fn";
    c3.FirstName = "ln";

    LinkedList<IClass> myList = new LinkedList<IClass>();
    myList.AddFirst(c1);
    myList.AddFirst(c2);
    // false here
    MessageBox.Show("myList<IClass> contains c3? - " + (myList.Contains(c3)));

    LinkedList<Class1> myList1 = new LinkedList<Class1>();
    myList1.AddFirst(c1);
    myList1.AddFirst(c1);
    // true here
    MessageBox.Show("myList1<Class1> contains c3? - " + (myList1.Contains(c3)));
}
+6  A: 

Since a linked list isn't a dictionary, I would expect it to use EqualityComparer<T>.Default.Equals(x,y).

This supports (in order):

  • IEquatable<T> (for the T in question)
  • object.Equals (which uses reference equality by default, or supports an overridden Equals(object))

Note that EqualityComparer<T> also handles the usual null rules etc for both classes and Nullable<T>.

(update: checked, and correct; from Find(T))

...
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
...
if (comparer.Equals(head.item, value)) {...}
...


Update to prove this working when ISomeInterface: IEquatable<ISomeInterface>, as per comments:

using System;
using System.Collections.Generic;


class Program
{
    static void Main()
    {
        LinkedList<IFoo> foos = new LinkedList<IFoo>();
        foos.AddLast(new Foo1("abc"));
        foos.AddLast(new Foo2("def"));
        Console.WriteLine("checking contains...");
        bool c = foos.Contains(new Foo1("ghi"));
        Console.WriteLine("...done");
    }
}
interface IFoo : IEquatable<IFoo>
{
    void Bar();
}
class Foo1 : IFoo
{
    public string Value { get; set; }
    public Foo1(string value) { Value = value; }
    public override bool Equals(object other)
    {
        Console.WriteLine(Value + " > override Equals");
        return base.Equals(other);
    }
    bool IEquatable<IFoo>.Equals(IFoo other)
    {
        Console.WriteLine(Value + " > explicit Equals");
        return base.Equals(other);
    }
    public void Bar() { }
    public override int GetHashCode() { return base.GetHashCode(); }
}
class Foo2 : IFoo
{
    public string Value { get; set; }
    public Foo2(string value) { Value = value; }
    public override bool Equals(object other)
    {
        Console.WriteLine(Value + " > override Equals");
        return base.Equals(other);
    }
    public bool Equals(IFoo other)
    {
        Console.WriteLine(Value + " > implicit Equals");
        return base.Equals(other);
    }
    public void Bar() { }
    public override int GetHashCode() { return base.GetHashCode(); }
}
Marc Gravell
yes, could you see the code I posted in the topic?the problem is that the linkedList contains an interface.But the objects implements the IEquitable interface as well.
serhio
Different `T`; they would need to implement `IEquatable<IClass>` for `LinkedList<IClass>` to use it.
Marc Gravell
Or more specifically, you would need `IClass : IEquatable<IClass>`, as it needs to be true for **all** `IClass` implementations.
Marc Gravell
no, the implementation of IEquitable is not sufficient if linkedList<T> T type is not the type implementing IEquitable<T>.In this case I need overriding the object Equals method.
serhio
Yes it is - see example in update (and my comment above this)
Marc Gravell
A: 

Reflector

Ruben Bartelink
your link is broken
serhio
@serhio, thanks. Damn [hypen-sites](http://blog.stackoverflow.com/2009/08/us-versus-hyphen/)
Ruben Bartelink
+1  A: 

The method to implement is the Equals. I need to implement the basic Equals method, and not necessarily(?!) the generic one.

class Class1 : IClass, IEquatable<Class1>
{
    public string FirstName;
    public string LastName;

    string IClass.GetName() { return FirstName; }

    bool IEquatable<Class1>.Equals(Class1 other)
    {
        return FirstName.Equals(other.FirstName);
    }

    public override bool Equals(object obj)
    {
        if (obj is Class1)
        {
            return this.FirstName.Equals((obj as Class1).FirstName);
        }
        else
        {
            return base.Equals(obj);
        }
    }
}
serhio
@serhio: FYI in general stuff like this gets edited into your question [though you mightnt have had then points at the start]
Ruben Bartelink
this is already a answer that I found, not part of question.
serhio