Вопрос

Я думал, что этот метод был действительным, но я был неправ:

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top