Оператор '==' нельзя применить к типу T?
-
24-10-2019 - |
Вопрос
Я думал, что этот метод был действительным, но я был неправ:
static void Equals<T>(T x, T y)
{
return x == y; //operator == can't be applied to type T
}
После прочтения спецификации (§7.2.4 в v3.0 и §7.3.4 в v4.0):
7.2.4 Разрешение перегрузки бинарного оператора
Операция формы x Op y, где OP является перегруженным бинарным оператором, x является выражением типа X, а Y является выражением типа Y, обрабатывается следующим образом:
Определяется набор кандидатов, определенных пользовательными операторами, предоставленный X и Y для оператора оператора OP (X, Y). Набор состоит из союза операторов -кандидатов, предоставленных X и операторами -кандидатами, предоставленными Y, каждый из которых определяется с использованием правил §7.2.5. Если x и y являются одинаковым типом, или если x и y получены из общего базового типа, то общие операторы кандидатов встречаются только в комбинированном наборе один раз.
Если набор кандидатов, определенных пользователем операторов, не является пустым, то это становится набором операторов кандидатов для операции. В противном случае, предопределенные бинарные операторы OP, включая их поднятые формы, становятся набором операторов -кандидатов для операции. Предопределенные реализации данного оператора указаны в описании оператора (с 7.7 по с 7.11).
Правила разрешения перегрузки §7.4.3 применяются к набору операторов кандидатов, чтобы выбрать лучшего оператора в отношении списка аргументов (x, y), и этот оператор становится результатом процесса разрешения перегрузки. Если разрешение перегрузки не может выбрать одного лучшего оператора, возникает ошибка времени компиляции.
На шаге 2 я думаю, что эта предопределенная реализация должна быть применена:
bool operator ==(object x, object y);
bool operator !=(object x, object y);
так как все в C# происходит от объекта. Как может возникнуть ошибка времени компиляции на шаге 3? Я не думаю, что возможно, что «разрешение перегрузки не может выбрать» в этом случае.
РЕДАКТИРОВАТЬ Вопрос пришел мне в голову, когда я реализовал что -то вроде этого:
class EnumComparer<TEnum> : IEqualityComparer<TEnum>
{
public bool Equals(TEnum x, TEnum y)
{
return x == y;
}
public int GetHashCode(TEnum obj)
{
return (int)obj;
}
}
Боюсь, мне нужно построить выражение и динамично вызвать его в Equals
метод
Решение
Хорошо, что вы читаете спецификацию, но вы перестали читать слишком рано. Если бы вы прочитали дальше, вы бы добрались до этого:
Предопределенные операторы равенства типа ссылки требуют одного из следующих:
Оба операнда являются значением типа, который, как известно, является эталонным типом или буквальным нулем. Кроме того, явное преобразование ссылки существует из типа любого операнда до типа другого операнда.
Один операнд-это значение типа t, где t-параметр типа, а другой операнд-буквальный нулевой. Кроме того, t не имеет ограничения типа значения.
Если одно из этих условий не верно, возникает ошибка времени привязки. (*)
Ошибка не из разрешения перегрузки; Ошибка заключается в том, что разрешение перегрузки выбрало бы предварительно определенного оператора равенства эталонного типа, и у вас нет ссылочных типов.
Рассмотрим свой код. Что останавливает t быть типом значения без оператора равенства, не определенного на нем? Ничего такого. Предположим, мы вернулись к версии объекта; Оба операнда были бы в разных местах и, следовательно, были эталонными, даже если у них был один и тот же контент. Поскольку это медленно, сбивает с толку и неправильно, это незаконно даже пытаться.
Почему вы пытаетесь сделать это в первую очередь? Если ваш метод сработал, а это не так, то ваш метод будет худший чем просто использовать == в первую очередь. Какую ценность вы собираетесь добавить в мир этим методом?
(*) Я сообщил о грамматической ошибке в этом предложении со стороны спектаклей.
Другие советы
Это могло бы сработать, если бы знал, что where T : class
, проводя справочное сравнение. Операторы, как правило, очень мало поддерживают дженерики, но есть обходные пути. Ошибка предложений косвенная поддержка операторов на дженериках, в противном случае EqualityComparer<T>.Default.Equals(x,y)
хороший выбор.
Я люблю использовать EqualityComparer<T>.Default
для этого.
Он основан на переопределенном Equals
метод, но использует IEquatable<T>
При наличии, избегая бокса по типам значений, реализуя его.
EqualityComparer<T>.Default.Equals(x, y)
использовать .Equals()
метод и убедитесь, что T
осуществлять IComparable