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

Если у меня есть этот код, он скомпилируется и будет работать как следует:

class MyNumber // Just a class.
{
    static public explicit operator MyNumber(byte b)
    {
        return new MyNumber();
    }
}

Decimal d = new Decimal();
MyNumber c1 = (MyNumber)d;

Поражение некоторых людей немного удивляет, поскольку не существует явного приведения decimal в MyNumber, Но так как есть явное приведение от decimal в byte и есть также явное приведение от byte в MyNumber, компилятор достаточно любезен, чтобы вставить это дополнительное явное приведение для меня.

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

Итак... Я попробовал то же самое на своих занятиях. Вместо byte а также decimal, Я использовал MyByte а также Mydecimal, Код выглядит так:

class MyDecimal // Simulates a decimal.
{
    static public explicit operator MyByte(MyDecimal a) // Just like in a decimal.
    {
        return new MyByte();
    }
}

class MyByte // Simulates a byte.
{
}

class MyNumber // Just a class.
{
    static public explicit operator MyNumber(MyByte b)
    {
        return new MyNumber();
    }
}

MyDecimal d = new MyDecimal();
MyNumber c2 = (MyNumber)d; // <== Will not compile!

Последняя строка не скомпилируется. Выдает ошибку: "Невозможно преобразовать тип" DoubleExplicitCasts.Program.MyDecimal "в" DoubleExplicitCasts.Program.MyNumber "". А почему бы не???

Поэтому мой вопрос таков: почему явные операторы внутри системы.NET получают специальную обработку, а мои пользовательские явные операторы - нет?

РЕДАКТИРОВАТЬ
Я знаю, что этот код не работает, и значения не передаются из одного экземпляра в другой, но это не относится к делу.

2 ответа

Ну, тривиально, потому что именно так это определяется стандартом C#.

Из раздела 6.4.3:

Оценка определенного пользователем преобразования никогда не включает в себя более одного определенного пользователем или отмененного оператора преобразования. Другими словами, преобразование из типа S в тип T никогда не выполнит пользовательское преобразование из S в X, а затем выполнит пользовательское преобразование из X в T.

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

  1. Это позволило бы возможность слишком много "удивительных" конверсий
  2. Это сделало бы процесс компиляции слишком медленным (возможный комбинационный взрыв)

но это только предположение с моей стороны.

IMO, это привело бы к "счастливой отладке" и действительно, очень сложному и неочевидному коду.

Представьте себе 3 или более уровней таких пользовательских преобразований, и как бы вы искали ошибку, вызванную преобразованием в середине (например, такое преобразование было введено по ошибке или не должно использоваться в такой ситуации).

Слава Богу, такое поведение не поддерживается.

Другие вопросы по тегам