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 literals的转换缩小为Single,而不是在任何其他情况下.
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)
在我看来,这可能是更可取的,但我可以理解为什么语言设计者会认为这种语法太混乱了.