Ответ 1
Метод Contains не использует оператор ==
Нет - он использует Equals
, который вы не переопределили... поэтому вы получаете поведение по умолчанию Equals
, которое вместо этого должно проверять ссылочный идентификатор. Вы должны переопределить Equals(object)
и GetHashCode
чтобы они были согласованы друг с другом - и для здравого смысла, в соответствии с вашей перегрузкой ==
.
Я также рекомендую использовать IEquatable<Element>
, который List<Element>
будет использовать в предпочтении Equals(object)
, в качестве EqualityComparer<T>.Default
подбирает его соответствующим образом.
О, и ваши перегрузки оператора должны обрабатывать и нулевые ссылки.
Я также настоятельно рекомендую использовать частные поля вместо публичных и сделать ваш тип неизменным - запечатать его и сделать id
чтения. Реализация равенства для изменяемых типов может привести к возникновению нечетных ситуаций. Например:
Dictionary<Element, string> dictionary = new Dictionary<Element, string>();
Element x = new Element(10);
dictionary[x] = "foo";
x.id = 100;
Console.WriteLine(dictionary[x]); // No such element!
Это произошло бы потому, что хэш-код будет меняться (по крайней мере, в большинстве реализаций), поэтому хеш-таблица, лежащая в основе словаря, не сможет найти даже ссылку на тот же объект, что уже там.
Таким образом, ваш класс будет выглядеть примерно так:
internal sealed class Element : IEquatable<Element>
{
private readonly int id;
public int Id { get { return id; } }
public Element(int id)
{
this.id = id;
}
public static implicit operator Element(int d)
{
return new Element(d);
}
public static bool operator ==(Element e1, Element e2)
{
if (object.ReferenceEquals(e1, e2))
{
return true;
}
if (object.ReferenceEquals(e1, null) ||
object.ReferenceEquals(e2, null))
{
return false;
}
return e1.id == e2.id;
}
public static bool operator !=(Element e1, Element e2)
{
// Delegate...
return !(e1 == e2);
}
public bool Equals(Element other)
{
return this == other;
}
public override int GetHashCode()
{
return id;
}
public override bool Equals(object obj)
{
// Delegate...
return Equals(obj as Element);
}
}
(Кстати, я не уверен в достоинстве неявного преобразования, я, как правило, держался подальше от них.)