Почему назначение Double для Single разрешено с опцией Strict On

почему следующий код не вызывает ошибку компиляции, хотя у меня есть Option Strict On?

Dim value As Single = 12345.12345  ' No error

числовой литерал по умолчанию интерпретируется компилятором как Double. Конверсии Double to Single является сужающим преобразованием (назначение, в этом случае, фактически округляет значение до 12345.123). Согласно статья MSDN, Option Strict On имеет следующий эффект:

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

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

Dim value As Single = 12345.12345R   'Still no error, despite the "R"

даже это не вызывает ошибку:

Dim value As Single = CDbl(12345.12345)   'Still no error, despite the CDbl() conversion

но это вызывает ошибку, так как я бы ожидайте:

Dim value1 As Double = 12345.12345
Dim value2 As Single = value1    ' Causes "Option Strict On disallows implicit conversions from 'Double' to 'Single'" error

аналогично, это также не, как и ожидалось:

Public Function GetValue() As Double
    Return 12345.12345
End Function

' ...

Dim value As Single = GetValue()   ' Causes "Option Strict On disallows implicit conversions from 'Double' to 'Single'" error

в качестве примечания, следующее не удается в C#, как и ожидалось:

float x = 12345.12345;  ' Causes error in C#

Итак, это не проблема со всеми языками .NET. Это просто кажется особенностью VB.NET - ...

кроме того, VB.NET не позволяет это неявное преобразование, даже если оно преобразуется из литерала:

Dim x As Integer = 1.5  ' Causes error

Итак, мой вопрос: почему VB.NET работать так? Кажется как недостаток для меня, но, возможно, есть хорошее объяснение, почему он позволяет сужать преобразования Double литералы к Single, а не в любой другой ситуации.

1 ответов


как указал Ганс в комментариях выше,VB.NET спецификация языка очень ясно по этой теме. В 11.2, в нем ясно говорится:

постоянные выражения интегрального типа (Long, Integer, Short, Byte) может быть неявно преобразован в более узкий интегральный тип и постоянные выражения типа Double можно неявно преобразовать в Single, при условии, что значение постоянного выражения в пределах диапазона типа назначения. Эти сужающие преобразования разрешены независимо от того, используется ли разрешительная или строгая семантика.

поскольку это поведение продиктовано спецификацией, это, очевидно, по дизайну. Пока Double значение является константой, неявное преобразование в Single всегда разрешено, даже если преобразование приводит к потере точности значения. Немного о "при условии, что значение постоянного выражения в диапазон типа назначения " в данном случае вводит в заблуждение. The Single тип поддерживает представление значений отрицательной бесконечности и положительной бесконечности, поэтому, когда Double значение находится вне допустимого диапазона Single type, он просто устанавливает его в одно из этих значений бесконечности.

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

Dim x As Single = 1 / 2

если Option Strict On запретить неявное преобразование от Double to Single, вы были бы вынуждены всегда писать что-то такое простое, как это:

Dim x As Single = 1.0F / 2.0F

или

Dim x As Single = CSng(1 / 2)

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