Подтвердить что ты не робот

С#, множественные == перегрузки оператора без двусмысленной нулевой проверки

Введение:
У меня есть несколько классов, которые выполняют ту же работу, но с разными типами значений (например, векторы поплавков или целых чисел).
Теперь я хочу иметь возможность проверить равенство, это равенство должно также работать между типами (такими как 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.
[...]

Вопрос:
Есть ли способ реализовать оператор == таким образом, что он позволяет простую проверку нуля и позволяет проверять равенство между разными векторами?

Альтернативно, есть ли другой способ, каким образом я мог/должен был это реализовать?

4b9b3361

Ответ 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...
}