2015-02-09 43 views
7

为什么下面的代码不会导致编译错误,即使我有Option Strict On为什么在选项严格的情况下允许从Double到Single分配

Dim value As Single = 12345.12345 ' No error 

默认情况下,数字文字由编译器解释为Double。从Double转换为Single是一个缩小的转换(分配,在这种情况下,实际上是将值四舍五入到12345.123)。按照MSDN articleOption 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这种工作方式?这对我来说似乎是一个缺陷,但也许有一个很好的解释,为什么它允许将文字的转换范围缩小到Single,但在其他任何情况下都不会。

+0

“*数字文字默认情况下由编译器解释为Double。*”您确定这是真的?你有参考吗?因为我认为它被解释为一个Single,就像历史上那样,VB/Basic的先前化身已经完成了它。 (这就是为什么我用附加的“#”编写这样的东西的原因。) – RBarryYoung 2015-02-09 17:11:55

+1

OK,根据这个:https://msdn.microsoft.com/en-us/library/dzy06xhf.aspx你是正确的... – RBarryYoung 2015-02-09 17:14:10

+1

非常奇怪!这也适用于没有投诉:Dim value As Single = Double.MaxValue以及Double.PositiveInfinity等 – theduck 2015-02-09 17:55:29

回答

4

正如Hans在上述评论中指出的,VB.NET language specification在这个话题上非常明确。在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不允许隐从DoubleSingle转换,你会不得不总是写的,像这样简单的东西:

Dim x As Single = 1.0F/2.0F 

或者

Dim x As Single = CSng(1/2) 

在我看来,这可以说是更可取的,但我可以理解为什么语言设计者会认为它的语法过于混乱。

+1

它仍然留下为什么Dim值为Single = Double.MaxValue,因为Double.MaxValue不在Single的范围内。 – theduck 2015-02-09 19:59:17

+0

@theduck真。事实上,Dim x As Single = 1E + 300'虽然超出了Single的范围。所以,显然无论是我对该部分含义的解释是不正确的,还是编译器略有缺失标记...... – 2015-02-09 20:06:15

+1

@theduck阅读第8.3节的最后一部分:对于从Double到Single的转换,Double值为四舍五入到最接近的单个值。如果Double值太小而不能表示为Single,则结果变为正零或负零。如果Double值太大而无法表示为Single,则结果变为正无穷或负无穷。如果Double值是NaN,那么结果也是NaN。 – 2015-02-09 20:51:34

相关问题