Перегрузка оператора ==,! =, Equals
Я уже прошел через question
Я понимаю, что необходимо реализовать ==
, !=
и Equals()
.
public class BOX
{
double height, length, breadth;
// this is first one '=='
public static bool operator== (BOX obj1, BOX obj2)
{
return (obj1.length == obj2.length
&& obj1.breadth == obj2.breadth
&& obj1.height == obj2.height);
}
// this is second one '!='
public static bool operator!= (BOX obj1, BOX obj2)
{
return !(obj1.length == obj2.length
&& obj1.breadth == obj2.breadth
&& obj1.height == obj2.height);
}
// this is third one 'Equals'
public override bool Equals(BOX obj)
{
return (length == obj.length
&& breadth == obj.breadth
&& height == obj.height);
}
}
Я предполагаю, что я правильно написал код, чтобы переопределить операторы ==
, !=
, Equals
. Хотя, я получаю ошибки компиляции следующим образом.
'myNameSpace.BOX.Equals(myNameSpace.BOX)' is marked as an override
but no suitable method found to override.
Итак, вопрос: как переопределить вышеперечисленные операторы и избавиться от этой ошибки?
Ответы
Ответ 1
Я думаю, вы объявили метод Equals
следующим образом:
public override bool Equals(BOX obj)
Поскольку метод object.Equals
принимает объект, нет способа переопределить эту подпись. Вы должны переопределить его следующим образом:
public override bool Equals(object obj)
Если вам нужен безопасный тип Equals,
, вы можете реализовать IEquatable<BOX>
.
Ответ 2
Как сказал Selman22, вы переопределяете метод по умолчанию object.Equals
, который принимает object obj
, а не тип безопасного времени компиляции.
Чтобы это произошло, создайте свой тип IEquatable<Box>
:
public class Box : IEquatable<Box>
{
double height, length, breadth;
public static bool operator ==(Box obj1, Box obj2)
{
if (ReferenceEquals(obj1, obj2))
{
return true;
}
if (ReferenceEquals(obj1, null))
{
return false;
}
if (ReferenceEquals(obj2, null))
{
return false;
}
return (obj1.length == obj2.length
&& obj1.breadth == obj2.breadth
&& obj1.height == obj2.height);
}
// this is second one '!='
public static bool operator !=(Box obj1, Box obj2)
{
return !(obj1 == obj2);
}
public bool Equals(Box other)
{
if (ReferenceEquals(null, other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
return height.Equals(other.height)
&& length.Equals(other.length)
&& breadth.Equals(other.breadth);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj.GetType() == GetType() && Equals((Box)obj);
}
public override int GetHashCode()
{
unchecked
{
int hashCode = height.GetHashCode();
hashCode = (hashCode * 397) ^ length.GetHashCode();
hashCode = (hashCode * 397) ^ breadth.GetHashCode();
return hashCode;
}
}
}
Еще одна вещь, которую нужно отметить, это то, что вы делаете сравнение с плавающей точкой, используя оператор равенства, и вы можете потерять точность.
Ответ 3
На самом деле это тема "как". Итак, вот эталонная реализация:
public class BOX
{
double height, length, breadth;
public static bool operator == (BOX b1, BOX b2)
{
if ((object)b1 == null)
return (object)b2 == null;
return b1.Equals(b2);
}
public static bool operator != (BOX b1, BOX b2)
{
return !(b1 == b2);
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
var b2 = (BOX)obj;
return (length == b2.length && breadth == b2.breadth && height == b2.height);
}
public override int GetHashCode()
{
return height.GetHashCode() ^ length.GetHashCode() ^ breadth.GetHashCode();
}
}
REF: https://msdn.microsoft.com/en-us/library/336aedhh(v=vs.100).aspx#Examples
ОБНОВЛЕНИЕ: приведение к (object)
в реализации operator ==
важно, в противном случае, оно будет повторно выполнять перегрузку оператора ==, что приведет к переполнению стека. Кредиты на @grek40.
Этот трюк (object)
от Microsoft String
== реализация.
SRC: https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/string.cs#L643