Почему проверка на равенство не допускает неявное преобразование типов объектов, но делает это для int? - PullRequest
1 голос
/ 07 декабря 2011

Почему C # допускает неявное преобразование объекта в int для сравнения на равенство, но не для сравнения типа объекта с типом объекта, даже если существует неявный оператор?

Строка bool errorHere = valueOnly == valuePair; дает исключение внизу.

class Program
{
    static void Main(string[] args)
    {
        ValueOnly valueOnly = new ValueOnly();
        ValuePair valuePair = new ValuePair();
        bool areEqual = valueOnly.Value == valuePair;
        bool errorHere = valueOnly == valuePair;
        bool butNotHere = valueOnly == (ValueOnly)valuePair;
        valueOnly = valuePair; // Or Here
    }
}

public class ValuePair
{
    public int Value { get; set; }
    public string Text { get; set; }

    public static implicit operator ValueOnly(ValuePair valuePair) {
        if (valuePair.Text != null || valuePair.Value != 0) {
            return new ValueOnly() { Value = valuePair.Value };
        }
        return null;
    }

    public static implicit operator int(ValuePair valuePair) {
        return valuePair.Value;
    }
}

public class ValueOnly
{
    public int Value { get; set; }
}

Вот ошибка:

Error   Operator '==' cannot be applied to operands of type 'ValueOnly' and 'ValuePair'

Ответы [ 2 ]

1 голос
/ 07 декабря 2011

C #, безусловно, не позволяет неявное преобразование объектов в int s для любых целей. Я не уверен, что вы имеете в виду строку

bool butNotHere = valueOnly == (ValueOnly)valuePair; 

как «разрешающий» такое преобразование. Если это так, он не делает ничего подобного. Он просто вызывает ваш собственный оператор преобразования (который, если я правильно прочитал код, вернет null, так как значение будет построенным по умолчанию целым числом), а затем выполняет сравнение ссылок между двумя объектами (которое оценивается как false как null не является ни чем-либо ссылочным).

Также само собой разумеется, что как только вы определили оператор неявного преобразования, C # будет использовать его всякий раз, когда это необходимо. Поэтому я думаю, что ваш вопрос больше связан с пониманием того, как работает оператор равенства на основе типов его аргументов, чем с чем-либо еще.

Обновление, касающееся проверки valueOnly == valuePair:

Спецификация C #, 7.10.6 (Операторы равенства ссылочного типа) гласит:

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

Если вы хотите иметь возможность сравнивать объекты типа класса на равенство, лучшим способом является реализация интерфейса IEquatable<T> и переопределение object.Equals для реализации в терминах IEquatable<T>.Equals (это означает, что вы будете также необходимо переопределить object.GetHashCode) для соответствия.

Однако при сравнении предметов полагаться на «скрытые» преобразования плохая идея. Если мы говорим о сравнении несвязанных классов, вы избавите себя от мучений в будущем, сделав сравнение как можно более заметным. Для этого я бы предложил низкотехнологичные

if(valuePair.Value == valueOnly.Value)
0 голосов
/ 07 декабря 2011

Чтобы разрешить valueOnly == valuePair, вы должны добавить это в класс ValuePair:

public static bool operator == (ValueOnly valueOnly, ValuePair valuePair){
    ValueOnly value = valuePair;
    return valueOnly.Value == value.Value;
}

При этом используется неявное преобразование, а затем выполняется проверка на равенство, которую я ищу ...

И теперь, когда я думаю об этом, неявное преобразование глупо (поскольку я не предоставил оператор равенства для класса ValueOnly):

public static bool operator == (ValueOnly valueOnly, ValuePair valuePair){
    return valueOnly.Value == valuePair.Value;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...