Неявные преобразования C # и оператор ==
-
23-08-2019 - |
Вопрос
Некоторый код для контекста:
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);