Вопрос

Некоторый код для контекста:

class a
{

}

class b
{
    public a a{get;set;}
    public static implicit operator a(b b)
    {
        return b.a;
    }
}

  a a=null;
  b b=null;
  a = b;

  //compiler: cannot apply operator '==' to operands of type tralala...
  bool c = a == b; 

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

Редактировать:
Если типы должны иметь одинаковый вызов ==, то почему

int a=1;
double b=1;
bool c=a==b; 

работает?

Это было полезно?

Решение

В implicit оператор работает только для назначения.

Вы хотите перегрузить равенство (==) оператор, как таковой:

class a
{
    public static bool operator ==(a x, b y)
    {
        return x == y.a;
    }

    public static bool operator !=(a x, b y)
    {
        return !(x == y);
    }
}

class b
{
    public a a{get;set;}
    public static implicit operator a(b b)
    {
        return b.a;
    }
}

Затем это должно позволить вам сравнить два объекта типа a и b как было предложено в вашем посте.

var x = new a();
var y = new b();
bool c = (x == y); // compiles

Примечание:

Я рекомендую просто переопределить GetHashCode и Equals метод, как предупреждает компилятор, но поскольку вы, похоже, хотите их подавить, вы можете сделать это следующим образом.

Измените объявление вашего класса в a Для:

#pragma warning disable 0660, 0661
class a
#pragma warning restore 0660, 0661
{
    // ...
}

Другие советы

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

ДА.

Что я пропустил?

Вот соответствующая часть спецификации.Вы пропустили выделенное слово.

Предопределенное равенство ссылочного типа операторы требуют, [чтобы] оба операнда были значениями ссылочного типа или буквальным значением null.Кроме того, a стандартный существует неявное преобразование из типа любого операнда в тип другого операнда.

Определяемое пользователем преобразование по определению не является стандартным преобразованием.Это ссылочные типы.Следовательно, заранее определенный оператор равенства ссылочного типа не является кандидатом.

Если типы должны быть одинаковыми, вызывающими ==, тогда почему [double == int] работает?

Ваше предположение о том, что типы должны быть одинаковыми, неверно.Существует стандартное неявное преобразование из int в double и есть оператор равенства, который принимает два удвоения, так что это работает.

Я думаю, вы тоже пропустили этот момент:

Это ошибка времени компиляции, чтобы использовать справочные равенство типа операторы сравнения двух ссылок что известно различной на во время компиляции.Например, если типы операндов во время компиляции являются двумя типами классов A и B, и если ни A, ни B не являются производными от другого, тогда было бы невозможно два операнда для ссылки на одно и то же объект.Таким образом, операция считается ошибкой времени компиляции.

Я бы предположил, что вам действительно нужно переопределить оператор == для интересующих вас типов.Вам придется поэкспериментировать с тем, будет ли компиляция / среда выполнения по-прежнему жаловаться, даже если типы неявно конвертируемы.

public static bool operator ==(a a, b b)
    {
        //Need this check or we can't do obj == null in our Equals implementation
        if (((Object)a) == null)
        {
            return false;
        }
        else
        {
            return a.Equals(b);
        }
    }

В качестве альтернативы просто используйте реализации Equals, как предлагает ole6ka, и убедитесь, что реализация выполняет приведение типов, которое вам нужно.

http://msdn.microsoft.com/en-us/library/8edha89s.aspx

В каждом случае один параметр должен быть того же типа, что и класс или структура который объявляет operator (...)

Используй это

 bool c = a.Equals(b);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top