Синтаксис для сравнения при поддержке IComparable - PullRequest
0 голосов
/ 06 ноября 2018

См. Код ниже. Под первой> второй красной линией находится волнистая линия Оператор не может быть применен к операндам OBJ и OBJ.

Есть ли какой-нибудь простой способ сделать то, что здесь задумано?

public static OBJ Swap<OBJ>(ref OBJ first, ref OBJ second) where OBJ : IComparable
{
    OBJ temp = first;
    OBJ temp2 = second;
    second = temp;
    first = temp2;
    if (first > second) return first else return second;
}

Ответы [ 3 ]

0 голосов
/ 06 ноября 2018

Если (i> j) работает, потому что int поддерживает IComparable.

Нет. Это неверно Это работает, потому что он реализует операторов сравнения . Например:

public static bool operator >(MyClass l, MyClass r) {
    return l.Value > r.Value;
}

Это не связано с IComparable , который требует, чтобы в реализации классов был определен один экземплярный метод :

public int CompareTo(object obj) {

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

Все, что вы говорите с public static OBJ Swap<OBJ>(ref OBJ first, ref OBJ second) where OBJ : IComparable, это то, что OBJ должен реализовывать IComparable - нет ничего подразумевающего, что переданный здесь тип будет иметь определенные операторы сравнения. Из-за этого компилятор не может позволить вам выполнять сравнения на равенство для объектов, для которых не могут быть определены операторы сравнения.

Я знаю, что вы думаете, «но компилятор может решить, что я передал во время компиляции», но помните, что на ваше скомпилированное приложение (даже в форме .exe) может ссылаться внешнее приложение, которое может передать неверный тип.

Вместо этого вы должны использовать CompareTo:

return a.CompareTo(b) > 0 ? a : b;
0 голосов
/ 06 ноября 2018

Причина, по которой вы получаете эту ошибку во время компиляции, состоит в том, что единственное ограничение, которое вы наложили на тип, состоит в том, что он реализует IComparable, единственный интерфейс, который гарантирует интерфейс, это метод CompareTo, и не все типы реализуют операторы сравнения.

Поскольку CompareTo гарантированно будет доступно, однако вы можете использовать его вместо этого.

Также обратите внимание, что вы должны использовать нулевой условный оператор (?.) при вызове метода CompareTo, поскольку существует вероятность, что first равен null (в этом случае вызов .CompareTo бросит ArgumentNullException).

Остальная часть вашего кода также может быть немного упрощена. Во-первых, вы можете немного сократить его, используя троичный оператор (?:), когда решаете, какой элемент вернуть. И, во-вторых, в операции подкачки вам нужна только одна переменная temp для хранения значения первой переменной, которую вы переназначаете. Например:

public static T Swap<T>(ref T first, ref T second) where T : IComparable
{
    var temp = first;
    first = second;
    second = temp;

    return first?.CompareTo(second) > 0 ? first : second;
}

Вот случай, когда значение null в противном случае выдает исключение, но с кодом выше оно работает как положено:

string first = null;
string second = "2";

string largest = Swap(ref first, ref second);
0 голосов
/ 06 ноября 2018
 if (first.CompareTo(second) > 0) return first else return second;
...