Неявный оператор приведения и оператор равенства - PullRequest
3 голосов
/ 23 марта 2012

Скажем, у меня есть простой объект, который поддерживает неявное приведение к System.String

public sealed class CompanyCode
{
    public CompanyCode(String value)
    {
        // Regex validation on value format
        _value = value;
    }

    private readonly String _value;

    public override String ToString()
    {
        return _value;
    }

    static public implicit operator String(CompanyCode code)
    {
        if(code == null)
            return null;

        return code.ToString();
    }
}

Теперь допустим, что в другой части моей программы я выполняю сравнение со строкой:

var companyCode = { some company code object }

if (companyCode == "MSFTUKCAMBS")
    // do something...

Что делает компилятор с оператором ==? Это неявное приведение companyCode к строке и запуск реализации System.String ==? Используется ли реализация System.Object ==? Или компилятор будет просто жаловаться на меня? (У меня нет компилятора, чтобы проверить это прямо сейчас).

Насколько я вижу, у меня есть несколько других вариантов.

  • Реализация оператора ==(String x) в CompanyCode.
  • Реализация интерфейса IEquatable<String> в CompanyCode.

Будет ли какой-либо (или оба) из этих вариантов предпочтительнее?

Ответы [ 3 ]

5 голосов
/ 23 марта 2012

Скажем, у меня есть простой объект, который поддерживает неявное приведение к System.String

Я бы поставил под сомнение это дизайнерское решение для начала. Тот факт, что он поднял этот вопрос о перегрузке операторов, предполагает, что ваши коллеги будут задавать такие же вопросы. Я даже не знаю ответа (с точки зрения того, что будет делать компилятор) с моей головы.

Я определенно не буду предлагать реализацию IEquatable<string>, так как тогда x.Equals(y) не будет симметричным с y.Equals(x). Вы могли бы реализовать две перегрузки == в вашем классе, в обе стороны ... но тогда это не будет соответствовать Equals.

Я бы предложил просто иметь свойство с именем Value или Code типа string, тогда вы можете использовать:

if (companyCode.Value == "MSFTUKCAMBS")

и сразу станет ясно, что это значит.

В принципе, я думаю, что ситуации, когда неявные преобразования являются подходящими, очень редки и весьма далеки.

Из Руководства по проектированию для разработчиков библиотек классов

Не указывайте оператора преобразования, если конечное пользователи явно не ожидают такого преобразования.

Есть ли здесь такое четкое ожидание?

2 голосов
/ 23 марта 2012

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

Неявного преобразования обычно следует избегать.Реализация == позволяет сравнивать со строкой, а IEquatable просто позволяет использовать класс в качестве типа IEquatable для внешних ссылок кода.IEquatable вполне может просто вернуть результат ==.

В этом случае я бы выбрал перегрузку оператора ==, если только у вас нет других целей для использования неявного преобразования.

Также,если вы используете неявные преобразования, будет немного уродливее код, но разумнее будет перегружать преобразование EXPLICIT, а не неявное, поэтому всякий раз, когда кто-то захочет преобразовать ваш класс в строку, он должен будет привести егоиспользование (string) obj, которое также является хорошим напоминанием о том, что действительно происходит в коде.

2 голосов
/ 23 марта 2012

Я бы лично предложил не использовать operator overloading, в этих случаях .Это немного сбивает с толку, глядя на код, чтобы понять, что происходит.

Это намного лучше, имхо, иметь какую-то функцию, которая явно проявляет операцию сравнения или, как предлагает Джон, использовать свойство.

Вкратце объясните читателю своего кода, что вы собираетесь сравнивать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...