为什么Option Strict On允许分配Double to Single

Ste*_*art 7 .net vb.net visual-studio

为什么以下代码不会导致编译错误,即使我有Option Strict On

Dim value As Single = 12345.12345  ' No error
Run Code Online (Sandbox Code Playgroud)

默认情况下,数字文字由编译器解释为Double.从转换DoubleSingle被收缩转换(分配,在这种情况下,实际上是舍入值12345.123).根据MSDN文章,Option Strict On具有以下效果:

将隐式数据类型转换限制为仅扩展转换,禁止后期绑定,并禁止导致Object类型的隐式类型.

基于该描述,我的示例代码应该导致错误.实际上,即使我在文字后明确指定了类型字符,它仍然不会将其视为错误:

Dim value As Single = 12345.12345R   'Still no error, despite the "R"
Run Code Online (Sandbox Code Playgroud)

即便这样也不会导致错误:

Dim value As Single = CDbl(12345.12345)   'Still no error, despite the CDbl() conversion
Run Code Online (Sandbox Code Playgroud)

但是,这确实会导致错误,正如我所期望的那样:

Dim value1 As Double = 12345.12345
Dim value2 As Single = value1    ' Causes "Option Strict On disallows implicit conversions from 'Double' to 'Single'" error
Run Code Online (Sandbox Code Playgroud)

同样,这也如预期的那样失败:

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
Run Code Online (Sandbox Code Playgroud)

作为旁注,正如预期的那样,C#中的以下内容失败:

float x = 12345.12345;  ' Causes error in C#
Run Code Online (Sandbox Code Playgroud)

因此,它不是所有.NET语言的问题.它似乎只是VB.NET的一个特点.

此外,VB.NET不允许这种隐式转换,即使它是从文字转换:

Dim x As Integer = 1.5  ' Causes error
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是,为什么VB.NET以这种方式工作?这对我来说似乎是一个缺陷,但也许有一些很好的解释,为什么它允许缩小Double文字的转换Single,但不能在任何其他情况下.

Ste*_*art 4

As Hans has pointed out in the comments above, the VB.NET language specification is very clear on this topic. In section 11.2, it clearly states:

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.

由于此行为是由规范规定的,因此显然是设计使然。只要Doublevalue 是常量,Single就始终允许隐式转换为,即使转换导致值丢失精度。在这种情况下,有关“假设常量表达式的值在目标类型的范围内”的位会产生误导。该Single类型支持表示负无穷大和正无穷大的值,因此当某个Double值超出该Single类型的有效范围时,它只是将其设置为这些无穷大值之一。

至于这种行为的设计决策背后的基本原理,我不能肯定地说,但我怀疑它是为了允许更方便的语法,如下所示:

Dim x As Single = 1 / 2
Run Code Online (Sandbox Code Playgroud)

如果不允许从toOption Strict On进行隐式转换,您将被迫总是编写像这样简单的东西:DoubleSingle

Dim x As Single = 1.0F / 2.0F
Run Code Online (Sandbox Code Playgroud)

或者

Dim x As Single = CSng(1 / 2)
Run Code Online (Sandbox Code Playgroud)

在我看来,这可以说是更好的选择,但我可以理解为什么语言设计者会认为它的语法太混乱了。