Почему назначение 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)
что, на мой взгляд, было бы предпочтительнее, но я могу понять, почему языковые дизайнеры решили, что синтаксис этого будет слишком запутанным.