С#, множественные == перегрузки оператора без двусмысленной нулевой проверки
Введение:
У меня есть несколько классов, которые выполняют ту же работу, но с разными типами значений (например, векторы поплавков или целых чисел).
Теперь я хочу иметь возможность проверить равенство, это равенство должно также работать между типами (такими как vectorF == vectorI).
Кроме того, должно быть возможно выполнить нулевую проверку (vectorF == null).
Подход:
Мой подход заключается в создании нескольких перегрузок для операторов == и! =, По одному для каждой возможной комбинации.
public sealed class VectorF
{
[...]
public static bool operator == (VectorF left, VectorI right)
{
// Implementation...
}
public static bool operator == (VectorF left, VectorF right)
{
// Implementation...
}
// Same for != operator
[...]
}
Проблема:
Используя множественные перегрузки, я не могу просто выполнить нулевую проверку с помощью оператора ==, поскольку вызов будет неоднозначным.
var v = new VectorF([...]);
if (v == null) // This call is ambiguous
[...]
Я знаю о возможности использовать ReferenceEquals или null casting вместо этого, но этот подход является серьезным ограничением для меня.
var v = new VectorF([...]);
if(object.ReferenceEquals(v, null)) // Would work, is not user friendly.
[...]
if(v == (VectorF)null) // Would also work, is neither user friendly.
[...]
Вопрос:
Есть ли способ реализовать оператор == таким образом, что он позволяет простую проверку нуля и позволяет проверять равенство между разными векторами?
Альтернативно, есть ли другой способ, каким образом я мог/должен был это реализовать?
Ответы
Ответ 1
Я бы отскочил назад от всего дизайна. Я бы никогда не реализовал ==
с семантикой значений между разными типами, я бы счел это довольно запутанным: instaceTypedA == instanceTypedB
кричит ссылочное равенство (по крайней мере, для меня).
Если вам нужно, чтобы это работало, тогда реализуйте неявное преобразование между VectorI
и VectorF
. Вот как работает структура. Когда вы выполните следующее:
int i = 1;
double d = 1;
var b = i == d;
Овелье ==(int, double)
не создано магией. Случается, что i
неявно преобразуется в double
и ==(double, double)
вызывается.
Ответ 2
Вы можете обойти сравнение с помощью is
:
if (v is VectorF)
Эта проверка завершится с ошибкой, если v
- null
.
Ответ 3
Что бы я сделал в этом случае, чтобы не перегружать оператор ==
, а вместо этого делать что-то вроде:
public static bool operator == (VectorF left, object right) {
if (object.ReferenceEquals(null, right)) {
// handle null case
}
VectorF rightF = right as VectorF;
if (!object.ReferenceEquals(null, rightF)) {
// Compare VectorF
}
VectorI rightI = right as VectorI;
if (!object.ReferenceEquals(null, rightI)) {
// Compare VectorI
}
// and so on...
}