2015-02-09 82 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

相關問題