2017-02-21 35 views
19

Введения:
У меня есть несколько классов, которые делают ту же работу, но с разными типами значений (например, векторы поплавков или целыми).
Теперь я хочу иметь возможность проверить равенство, это равенство должно также работать между типами (такими как vectorF == vectorI).
Также должно быть возможно выполнить нулевую проверку (vectorF == null).C#, несколько операторов == Перегрузки без неоднозначных нулевой проверки

подход:
Мой подход заключается в создании нескольких перегруженных для == и = операторы, один для каждой возможной комбинации!.

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 или нулевую отливку вместо этого, но что approachis серьезного ограничения для меня.

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. 
[...] 

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

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

+5

Похоже, что ваши классы Vector действительно должны быть неизменяемыми структурами. Тогда вопрос «null» не возникает. (Я предполагаю, что ваши классы содержат только 2 или 3 значения.) –

+2

Похоже на [zugzwang] (https://en.wikipedia.org/wiki/Zugzwang): либо красивый '==' или '== null '. Как насчет методов сравнения с вектором другого типа? Например. 'VectorF.IsSame (VectorI) '? Компилятор покажет ошибку пользователя, когда он попробует 'vectorF == vectorI', а затем пользователь будет искать методы для сравнения, tada, решить проблему? Другое дело: сравнение 'float' с' int' было бы неточным, как насчет того, чтобы вначале «VectorF» в «VectorI», а затем сравнивая два «VectorI»? – Sinatr

+0

Почему вам нужны левые и правые перегрузки .. Могу ли вы поделиться с нами перегруженными методами. – levent

ответ

20

Я бы отодвинуть на всей конструкции, чтобы начать с. Я бы никогда не реализовал == со смысловой семантикой между различными типами, я бы счел это довольно запутанным: instaceTypedA == instanceTypedB кричит ссылочное равенство (по крайней мере, для меня).

Если вам это нужно, выполните неявное преобразование между VectorI и VectorF. Вот как работает структура. Когда вы делаете следующее:

int i = 1; 
double d = 1; 
var b = i == d; 

oveload ==(int, double) не волшебно производства. Случается, что i неявно преобразован в double и вызывается ==(double, double).

+0

Спасибо. Вы правы, == должно быть ссылкой на равенство. Я не думал о неявном преобразовании, поскольку я хотел, чтобы вызов был максимально оптимизирован. Однако, поскольку значения будут преобразованы в любом случае, это не имеет большого значения в конце концов. – Chillersanim

8

Вы можете повернуть вокруг сравнения с помощью is:

if (v is VectorF) 

Эта проверка будет выполнена, если v является null.

+0

очень приятно, что это действительно хорошее решение! –

+5

Мне не нравится это решение. Семантика того, что вы на самом деле делаете, скрыта в «умном» трюке; читая этот код, это далеко не ясно, что вы проверяете «null», если честно. – InBetween

+1

Ну, довольно часто бывает проверять тип с помощью 'is' (или' as'), хотя не все знают, что это тоже нулевая проверка. Как только вы узнаете, что совершенно очевидно, что 'null' не имеет определенного типа. –

2

Что я буду делать в этом случае не перегружать оператор ==, и вместо того, чтобы сделать что-то вроде:

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... 
} 
+2

Ewww, жертвуя безопасностью типа времени компиляции, чтобы сохранить повторение нулевой проверки? –

 Смежные вопросы

  • Нет связанных вопросов^_^