2009-07-06 72 views
59

我有一個IDataRecord reader我正在檢索小數從如下:「指定的轉換無效」爲什麼我不能將int作爲小數來取代?

decimal d = (decimal)reader[0]; 

出於某種原因,這將引發一個無效的轉換異常說,

當我做reader[0].GetType()它告訴我,它是一個Int32。據我所知,這應該不是一個問題....

我已經測試了這一點,這段代碼工作得很好。

int i = 3750; 
decimal d = (decimal)i; 

這讓我撓腦袋,想知道爲什麼它無法將閱讀器中包含的int作爲小數來解開。

有誰知道爲什麼會發生這種情況?我錯過了些微妙的東西嗎?

回答

74

只能將值類型解除其原始類型(以及該類型的可爲空的版本)。

順便說一句,這是有效的(只是爲你的兩個行版本的簡寫):

object i = 4; 
decimal d = (decimal)(int)i; // works even w/o decimal as it's a widening conversion 

對於背後的原因這個閱讀本Eric Lippert's blog entry: Representation and Identity

就個人而言,我歸類的東西被轉換語法做成(都擁有不同的IL指令)四種不同類型的操作:

  1. 拳擊(box IL指令)和拆箱(unbox IL指令)
  2. 通過inhertiance層級(如dynamic_cast<Type>在C++中鑄造,採用castclass IL指令來驗證)
  3. 原始類型(像在C static_cast<Type> ++,有大量的IL指令爲不同類型之間鑄件之間鑄造原始類型)
  4. 調用用戶定義的轉換運算符(在IL級別,它們只是方法調用到適當的op_XXX方法)。
+20

在某種意義上,它是一個恥辱,拆箱和鑄造語法看起來相同,因爲它們是非常不同的操作。 – jerryjvl 2009-07-06 01:59:14

+0

謝謝Mehrdad。你的解釋和鏈接到Eric的博客是相當有幫助的。 – mezoid 2009-07-06 02:29:36

14

在將int轉換爲decimal時沒有問題,但是當拆箱對象時,必須使用該對象包含的確切類型。

拆箱的int值轉換成decimal值,你先拆箱它作爲一個int,然後將其轉換爲十進制:

decimal d = (decimal)(int)reader[0]; 

的IDataRecord接口也有拆箱的價值的方法:

decimal d = (decimal)reader.GetInt32(0); 
3

邁赫達德Afshari說:

只能拆箱值TY pe的原始類型(以及該類型的可空值 版本)。

要實現的事情是,鑄造和拆箱之間是有區別的。 jerryjvl具有優良的言論

在某種意義上,它是一個恥辱,拆箱和鑄造語法看起來 相同的,因爲它們是非常不同的操作。

鑄造:

int i = 3750; // Declares a normal int 
decimal d = (decimal)i; // Casts an int into a decimal > OK 

拳擊/開箱:

object i = 3750; // Boxes an int ("3750" is similar to "(int)3750") 
decimal d = (decimal)i; // Unboxes the boxed int into a decimal > KO, can only unbox it into a int or int? 
12

下面是一個簡單的解決方案。它負責拆箱,然後轉換爲十進制。爲我工作得很好。

decimal d = Convert.ToDecimal(reader[0]); // reader[0] is int 
相關問題