Как переопределить оператор equals == для интерфейса в С#?
Я определил следующий интерфейс
public interface IHaveAProblem
{
string Issue { get; set; }
}
И вот реализация IHaveAProblem
public class SomeProblem : IHaveAProblem
{
public string Issue { get; set; }
public override bool Equals(object obj)
{
SomeProblem otherObj = obj as SomeProblem;
if (otherObj == null)
{
return false;
}
return this.Issue == otherObj.Issue;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public static bool operator ==(SomeProblem rhs, SomeProblem lhs)
{
// Null check
if (Object.ReferenceEquals(rhs, null) || Object.ReferenceEquals(lhs, null))
{
if (Object.ReferenceEquals(rhs, null) && Object.ReferenceEquals(lhs, null))
{
// Both are null. They do equal each other
return true;
}
// Only 1 is null the other is not so they do not equal
return false;
}
return rhs.Equals(lhs);
}
public static bool operator !=(SomeProblem rhs, SomeProblem lhs)
{
// Null check
if (Object.ReferenceEquals(rhs, null) || Object.ReferenceEquals(lhs, null))
{
if (Object.ReferenceEquals(rhs, null) && Object.ReferenceEquals(lhs, null))
{
// Both are null. They do equal each other
return false;
}
// Only 1 is null the other is not so they do not equal
return true;
}
return !rhs.Equals(lhs);
}
}
Когда я использую объект, я могу получить правильные результаты для сравнения ==.
SomeProblem firstTest = new SomeProblem()
{
Issue = "Hello World"
};
SomeProblem secondTest = new SomeProblem()
{
Issue = "Hello World"
};
// This is true
bool result = firstTest == secondTest;
Однако, когда я пытаюсь сравнить интерфейсы, он выполняет сравнение памяти, а не оператор == на SomeProblem
IHaveAProblem firstProblem = new SomeProblem()
{
Issue = "Hello World"
};
IHaveAProblem secondProblem = new SomeProblem()
{
Issue = "Hello World"
};
Возможно ли, что интерфейс использует == на SomeProblem, а не сравнение с памятью?
Я знаю, что могу сделать firstProblem.Equals(secondProblem)
и получить правильный результат, однако я создаю фреймворк, и я не буду знать, как он используется в конце. Я думал, что == будет работать правильно.
Ответы
Ответ 1
Оператор ==
является статическим. Вы не можете определить статические методы для интерфейсов в С#. Кроме того, для всех операторов хотя бы один из типов аргументов должен быть того же типа, что и класс, в котором он определен, поэтому: Нет перегрузки оператора для интерфейсов: (
Что вы можете сделать, так это использовать абстрактный класс - и определить там оператор. Опять же, оператор НЕ может быть виртуальным (поскольку статические методы не могут быть виртуальными...)
[Отредактировано, причина см. комментарий.]
Ответ 2
IIRC (и я могу ошибаться здесь), интерфейсы С# не позволяют перегрузке оператора.
Но в этом случае все в порядке. Оператор == обычно отображается на ссылочное равенство. Похоже, вам нужно равенство ценности, и это означает, что вы хотите заставить их переопределить функции .Equals()
(и, следовательно, также .GetHashCode()
). Вы делаете это, наследуя свой интерфейс от IEquatable()
.
Ответ 3
I konw, это старый вопрос, но все представленные примеры показывают, как сравнивать два экземпляра класса, и никто не указывает, как сравнивать два экземпляра интерфейса.
В некоторых случаях это самый DRY-способ сравнения интерфейсов.
public interface IHaveAProblem
{
string Issue { get; set; }
}
public class IHaveAProblemComparer : IComparer<IHaveAProblem>, IEqualityComparer<IHaveAProblem>
{
public int Compare(IHaveAProblem x, IHaveAProblem y)
{
return string.Compare(x.Issue, y.Issue);
}
public bool Equals(IHaveAProblem x, IHaveAProblem y)
{
return string.Equals(x.Issue, y.Issue);
}
public int GetHashCode(IHaveAProblem obj)
{
return obj.GetHashCode();
}
}
Использование
IHaveAProblemComparer comparer = new IHaveAProblemComparer();
List<IHaveAProblem> myListOfInterfaces = GetSomeIHaveAProblemObjects();
myListOfInterfaces.Sort(comparer); // items ordered by Issue
IHaveAProblem obj1 = new SomeProblemTypeA() { Issue = "Example1" };
IHaveAProblem obj2 = new SomeProblemTypeB() { Issue = "Example2" };
bool areEquals = comparer.Equals(obj1, obj2); // False
Ответ 4
В С# операторы статичны и переопределяют статические методы... messy.
Почему бы вам просто не переопределить метод Equals(), который унаследован от объекта? Это довольно просто, и вам не пришлось бы вмешиваться в переопределение статических методов.
Ответ 5
Вы пытались реализовать IComparable?
Вот так:
public interface IHaveAProblem : IComparable
{
string Issue { get; set; }
}
И затем в реализации класса:
public class SomeProblem : IHaveAProblem
{
public string Issue { get; set; }
...
public int CompareTo(object obj)
{
return Issue.CompareTo(((SomeProblem)obj).Issue);
}
}
Обратите внимание, что это работает только при сравнении двух экземпляров SomeProblem, но не с любыми другими реализациями интерфейса IHaveAProblem.
Не уверен, что может возникнуть исключение NullReferenceException.