【问题标题】:Why is assignment of Double to Single allowed with Option Strict On为什么使用 Option Strict On 允许将 Double 分配给 Single
【发布时间】:2015-04-09 12:08:21
【问题描述】:

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

Dim value As Single = 12345.12345  ' No error

默认情况下,编译器将数字文字解释为Double。从Double 转换为Single 是一种缩小转换(在这种情况下,赋值实际上将值四舍五入为12345.123)。根据MSDN articleOption Strict On的作用如下:

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

根据该描述,我的示例代码应该会导致错误。事实上,即使我在字面量后显式指定类型字符,它仍然不会将其视为错误:

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,但在任何其他情况下都不允许。

【问题讨论】:

  • "默认情况下,数字文字被编译器解释为 Double。" 你确定这是真的吗?你有这方面的参考吗?因为我会假设它被解释为单曲,从历史上看,这就是 VB/Basic 的先前版本所做的。 (这就是为什么我在写这样的东西时附加一个“#”。)
  • 好的,根据这个:msdn.microsoft.com/en-us/library/dzy06xhf.aspx你是对的......
  • 很奇怪!这也可以毫无怨言地工作: Dim value As Single = Double.MaxValue 以及 Double.PositiveInfinity 等
  • 这似乎是基于问题和 cmets 的编译器错误...
  • 这有一个共同的答案:“因为语言规范说它是有效的”。第 11.2 节:“无论使用的是许可语义还是严格语义,都允许这些缩小转换。”

标签: .net vb.net visual-studio


【解决方案1】:

正如 Hans 在上面的 cmets 中指出的那样,VB.NET language specification 在这个主题上非常清楚。在section 11.2 中明确指出:

整数类型(LongIntegerShortByte)的常量表达式可以隐式转换为更窄的整数类型,Double 类型的常量表达式可以隐式转换为@ 987654328@,前提是常量表达式的值在目标类型的范围内。无论使用的是宽松语义还是严格语义,这些缩小转换都是允许的。

由于此行为是由规范规定的,因此显然是设计使然。只要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)

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

【讨论】:

  • 它仍然留下一个问题,为什么 Dim value as Single = Double.MaxValue 的作用是 Double.MaxValue 不在 Single 的范围内。
  • @theduck 是的。事实上,Dim x As Single = 1E+300 有效,尽管这超出了Single 的范围。所以,显然要么我对该部分含义的解释不正确,要么编译器略微遗漏了标记......
  • @theduck 阅读第 8.3 节的最后部分:对于从 Double 到 Single 的转换,Double 值会四舍五入到最接近的 Single 值。如果 Double 值太小而无法表示为 Single,则结果将变为正零或负零。如果 Double 值太大而无法表示为 Single,则结果将变为正无穷大或负无穷大。如果 Double 值为 NaN,则结果也是 NaN。
  • @Bjørn-RogerKringsjå 没错,所以当它在 11.2 中说 “只要常量表达式的值在目标类型的范围内” 时,它一定是指所有整数类型的常量,而不仅仅是 DoubleSingle。它只是措辞不准确,因为无论哪种方式都可以轻松阅读。
  • @StevenDoggart 英语不是我的母语,但我就是这么读的。我同意这有点模糊。
猜你喜欢
  • 1970-01-01
  • 2012-09-04
  • 1970-01-01
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 2019-06-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多