LinkedList.Contains. Quelle est la méthode utilisée pour comparer des objets?
-
20-09-2019 - |
Question
méthode LinkedList.Contains. (.NET 2)
Comment les objets sont comparés à l'intérieur? (Egal? CompareTo?)
MSDN dit rien.
la 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)));
}
La solution 2
Le procédé est de mettre en œuvre les pairs. Je dois mettre en œuvre la méthode Equals de base, et pas nécessairement (?!) le générique.
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);
}
}
}
Autres conseils
Comme une liste chaînée est pas un dictionnaire, je le ferais attendre à utiliser EqualityComparer<T>.Default.Equals(x,y)
.
prend en charge (dans l'ordre):
-
IEquatable<T>
(pour laT
en question) -
object.Equals
(qui utilise l'égalité de référence par défaut, ou prend en charge uneEquals(object)
substituée)
Notez que EqualityComparer<T>
gère également les règles de null
habituelles etc pour les classes et Nullable<T>
.
(mise à jour: vérifier et corriger, à partir de Find(T)
)
...
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
...
if (comparer.Equals(head.item, value)) {...}
...
Mise à jour pour prouver ce travail quand ISomeInterface: IEquatable<ISomeInterface>
, selon les commentaires:
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(); }
}