为什么 Option Strict On 允许将 Double 分配给 Single
Why is assignment of Double to Single allowed with Option Strict On
为什么下面的代码不会导致编译错误,即使我有 Option Strict On
?
Dim value As Single = 12345.12345 ' No error
默认情况下,数字文字被编译器解释为 Double
。从 Double
到 Single
的转换是缩小转换(在这种情况下,赋值实际上将值四舍五入为 12345.123
)。根据MSDN article,Option Strict On
有如下效果:
Restricts implicit data type conversions to only widening conversions, disallows late binding, and disallows implicit typing that results in an Object type.
根据该描述,我的示例代码应该会导致错误。事实上,即使我在文字后明确指定类型字符,它仍然不会将其视为错误:
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
,但在任何其他情况下都不允许。
正如汉斯在上面的评论中指出的那样,VB.NET language specification is very clear on this topic. In section 11.2 明确指出:
Constant expressions of an integral type (Long
, Integer
, Short
, Byte
) can be implicitly converted to a narrower integral type, and constant expressions of type Double
can be implicitly converted to Single
, provided the value of the constant expression is within the range of the destination type. These narrowing conversions are allowed regardless of whether permissive or strict semantics are being used.
由于此行为是由规范规定的,因此显然是设计使然。只要 Double
值是常量,就始终允许隐式转换为 Single
,即使转换导致值失去精度。在这种情况下,关于“前提是常量表达式的值在目标类型 的范围内”的内容具有误导性。 Single
类型支持表示负无穷大和正无穷大的值,因此当 Double
值超出 Single
类型的有效范围时,它只是将其设置为这些无穷大之一值。
至于这种行为的设计决定背后的基本原理,我不能肯定地说,但我怀疑这是为了允许更方便的语法,如下所示:
Dim x As Single = 1 / 2
如果 Option Strict On
不允许从 Double
到 Single
的隐式转换,你将被迫总是写一些像这样简单的东西:
Dim x As Single = 1.0F / 2.0F
或
Dim x As Single = CSng(1 / 2)
在我看来,这可以说是更可取的,但我能理解为什么语言设计者会认为这样的语法太混乱了。
为什么下面的代码不会导致编译错误,即使我有 Option Strict On
?
Dim value As Single = 12345.12345 ' No error
默认情况下,数字文字被编译器解释为 Double
。从 Double
到 Single
的转换是缩小转换(在这种情况下,赋值实际上将值四舍五入为 12345.123
)。根据MSDN article,Option Strict On
有如下效果:
Restricts implicit data type conversions to only widening conversions, disallows late binding, and disallows implicit typing that results in an Object type.
根据该描述,我的示例代码应该会导致错误。事实上,即使我在文字后明确指定类型字符,它仍然不会将其视为错误:
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
,但在任何其他情况下都不允许。
正如汉斯在上面的评论中指出的那样,VB.NET language specification is very clear on this topic. In section 11.2 明确指出:
Constant expressions of an integral type (
Long
,Integer
,Short
,Byte
) can be implicitly converted to a narrower integral type, and constant expressions of typeDouble
can be implicitly converted toSingle
, provided the value of the constant expression is within the range of the destination type. These narrowing conversions are allowed regardless of whether permissive or strict semantics are being used.
由于此行为是由规范规定的,因此显然是设计使然。只要 Double
值是常量,就始终允许隐式转换为 Single
,即使转换导致值失去精度。在这种情况下,关于“前提是常量表达式的值在目标类型 的范围内”的内容具有误导性。 Single
类型支持表示负无穷大和正无穷大的值,因此当 Double
值超出 Single
类型的有效范围时,它只是将其设置为这些无穷大之一值。
至于这种行为的设计决定背后的基本原理,我不能肯定地说,但我怀疑这是为了允许更方便的语法,如下所示:
Dim x As Single = 1 / 2
如果 Option Strict On
不允许从 Double
到 Single
的隐式转换,你将被迫总是写一些像这样简单的东西:
Dim x As Single = 1.0F / 2.0F
或
Dim x As Single = CSng(1 / 2)
在我看来,这可以说是更可取的,但我能理解为什么语言设计者会认为这样的语法太混乱了。