Почему мне нужно промежуточное преобразование для движения от структуры до десятичного числа, но не структуры к интервалу?

У меня есть структура как это с явным преобразованием для плавания:

struct TwFix32
{
    public static explicit operator float(TwFix32 x) { ... }
}

Я могу преобразовать TwFix32 в интервал с единственным явным броском: (int)fix32

Но преобразовать его в десятичное число, я должен использовать два броска: (decimal)(float)fix32

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

8
задан Jesse McGrew 10 May 2010 в 22:11
поделиться

1 ответ

Я часто не могу дать удовлетворительный ответ на вопросы «почему».

Причина, по которой компилятор C# демонстрирует такое поведение, заключается в том, что оно (в данном случае, по крайней мере, (*)) правильная реализация спецификации C#.

В разделе 6.4.5 спецификации описывается, как анализируются определяемые пользователем преобразования. Внимательное прочтение этого раздела объяснит, почему явное преобразование в int является законным, а в десятичное — нет.

В частности, соответствующий абзац:

Найдите набор применимых пользовательских и поднятых операторов преобразования, U. Этот набор состоит из определяемых пользователем и поднятых неявных или явных операторов преобразования, объявленных классами или структурами в D, которые преобразуются из типа, охватывающего или охватываемого S, в тип, охватывающий или охватываемый T. Если U пусто, преобразование не определено и возникает ошибка времени компиляции.

В вашем случае S — это TwFix, а T — это int или десятичная дробь. Единственное определяемое пользователем явное преобразование в TwFix возвращает плавающее значение. int охватывается float, но десятичная дробь не охватывается и не охватывает float.Поэтому множество U имеет член в одном случае и пусто в другом. Поэтому один случай приводит к ошибке, как сказано в спецификации, а другой нет.

У меня есть ощущение, что этот ответ не является удовлетворительным. Если нет, можете ли вы перефразировать вопрос так, чтобы в нем не было слова «почему»? Я намного лучше отвечаю на вопросы «что» или «как», чем на вопросы «почему».

(*) Компилятор имеет известные ошибки в коде, который вычисляет, охватывает ли один тип другой, с целью определения того, какие встроенные преобразования имеют значение при анализе семантики конкретного определяемого пользователем преобразования. Во многих случаях мы намеренно не исправляем эти ошибки, потому что это приведет к резкому изменению реального кода без большой пользы. Мне бы очень хотелось вернуться к этому разделу спецификации и переписать его таким образом, чтобы убрать понятие «охватывающий тип»; это немного странно в спецификации. И, как вы обнаружили,он создает эту странность, где float явно преобразуется в десятичное, а десятичное явно преобразуется в float, но поскольку ни один из них не охватывает другой, определяемый пользователем код явного преобразования не нравится. Однако это очень низкий приоритет.

8
ответ дан 5 December 2019 в 20:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: