2012-02-14 54 views
4

在以下代碼中,我期望var可以解析爲Int64,但它會解析爲double。爲什麼這樣?爲什麼var會以Double而不是Long來解析?

string a = "1234"; 
bool asInt = true; 
var b = (asInt) ? Int64.Parse(a) : Double.Parse(a) ; 
Console.WriteLine(b.GetType()); 
+1

即使編譯,我有點驚訝。我認爲三元的兩邊都必須返回相同的類型,儘管我認爲有一個從長到雙的隱含對話 – 2012-02-14 12:32:36

+0

有。 ,)這解釋了這一點。 – TomTom 2012-02-14 12:34:07

回答

12

有一個隱式轉換從Int64Double而不是其他方式(由於在該方向上的精度可能損失)。

由於條件的兩個「分支」都需要解析爲相同類型,因此b的類型最終被推斷爲Double

+0

有道理。有什麼辦法可以在需要時創建Int64類型的變量'b',並在需要時創建Double(基於bool'asInt')?當然,在if語句中初始化它是行不通的,因爲它的作用域限制在 – xbonez 2012-02-14 12:35:02

+0

@xbonez - 不在條件運算符中。該類型必須在運行時推斷/確定。你可以使用'dynamic'。 – Oded 2012-02-14 12:36:38

+0

嗯...謝謝。我會研究動態的。我知道數學運算在雙打上比較慢,所以我希望在不需要時不要使用雙精度。我會研究動態的,但如果這不起作用,我想我會忍受它。 – xbonez 2012-02-14 12:37:52

5

您可以隱式將long投射到double

不能隱式轉換一個doublelong

所以C#編譯器決定了變量類型的唯一可能性是double

請參閱Implicit Numeric Conversions Table

4

因爲編譯器需要推斷可以保存Int64.Parse(a)Double.Parse(a)的值而不需要顯式強制轉換的類型。如果推斷出long,則表達式的另一個偏差將會失去精度。

如果您需要區分類型,您必須聲明變量和重寫代碼:

if (asInt) 
{ 
    var b = Int64.Parse(a); // will infer a `long` 
    Console.WriteLine(b.GetType()); 
} 
else 
{ 
    var b = Double.Parse(a); // will infer a `double` 
    Console.WriteLine(b.GetType()); 
} 
+1

那麼,有沒有什麼辦法可以做你已經做的事情,但是能夠訪問if-else範圍之外的變量b? – xbonez 2012-02-14 12:36:41

+0

@xbonez,是的,但你應該將'b'定義爲'object'類型:'object b;' – Dims 2012-02-14 12:47:48

+0

完美...這就是我一直在尋找的東西。 「對象」正是我所需要的。謝謝! – xbonez 2012-02-14 12:49:34

1

C#編譯器從公分母推斷兩個返回類型之間的類型你三元。 Int64可以隱式轉換爲Double。反過來並非如此。

請注意,代碼示例中布爾的狀態與推斷類型無關。

0

這是?:操作員的工作。它應該將所有結果都轉換爲一種類型。

P.S. +運營商的類似行爲,你知道:

string a = "1234"; 
var b = Int64.Parse(a) + Double.Parse(a) ; 
Console.WriteLine(b.GetType()); 

P.P.S.有你想要你應該使用什麼object

string a = "1234"; 
bool asInt = true; 
object b; 
if(asInt) b=Int64.Parse(a); else b=Double.Parse(a); 
Console.WriteLine(b.GetType()); 

P.P.P.S.另一種選擇是:

 string a = "1234"; 
#if asInt 
     Int64 b = Int64.Parse(a); 
#else 
     Double b = Double.Parse(a); 
#endif 
     Console.WriteLine(b.GetType()); 

定義asInt中使用

#define asInt 
+0

不幸的是,'object'需要我將它轉換爲'Int64'或'double',然後才能對其執行任何操作,這是不可能的,因爲我直到運行時才知道該類型 – xbonez 2012-02-14 12:54:04

+0

然後嘗試條件編譯指令,'#if'等 – Dims 2012-02-14 13:18:35

+0

如果你不依賴算術運算符,你也可以使用泛型方法和/或類型。如果你是那麼你會做更多的技巧。 – Dims 2012-02-14 13:19:41

0

我很驚訝,沒有人指出,如果你知道值將是一個法律long值,可以更改編譯器的行爲與明確的強制轉換,並只使用long

根據確定asInt的值的條件以及您打算對錶達結果做什麼,這可能會也可能不會有所幫助。這裏有一個例子:

string a = "1234.56"; 
bool asDouble = a.Contains("."); 
var b = asDouble ? (long)Double.Parse(a) : Int64.Parse(a); 
Console.WriteLine(b.GetType()); 

事實上,在這個例子中,你不需要條件運算符;這將工作太:

string a = "1234.56"; 
var b = (long)Double.Parse(a); 
Console.WriteLine(b.GetType()); 

換句話說,它可能是最好的解決辦法不會用三元運算符,但問題並沒有給予足夠的情況下就知道了。

相關問題