2010-08-22 91 views
37

我有以下代碼:奇怪的鑄造行爲。不能投射對象(int)以長

int intNumber1 = 100; 
object intNumber2 = 100; 
bool areNumberOfTheSameType = intNumber1.GetType() == intNumber2.GetType(); // TRUE 
bool areEqual = intNumber1.Equals(intNumber2); // TRUE 

long longNumber1 = (long) intNumber1; // OK 
long longNumber2 = (long) intNumber2; // InvalidCastException. Why? 

爲什麼沒有第二科協工作?我意識到這可能是因爲該對象沒有明確的轉換時間,但如果我們在運行時查看它的類型,它是System.Int32

如果我使用vardynamic而不是object,它可以工作。

有什麼想法?

+4

嘗試將其更改爲 'long longNumber2 =(long)(int)intNumber2;' – 2010-08-22 13:50:21

+0

爲什麼要在此實例中使用對象而不是var?它更好地保持變量儘可能強烈鍵入 – 2010-08-22 13:55:46

+1

@ Quinn351:我的猜測是,上面的代碼說明了用戶有一個簡化的問題,我不認爲我們應該把它作爲當前的做法。 – Abel 2010-08-22 13:58:48

回答

42

投從intlong被解釋爲兩種類型之間的轉換。

投從objectint被解釋爲開盒裝int

這是相同的語法,但它說兩個不同的東西。

在工作例(intlongobject(盒裝int)→int),編譯器知道到底是什麼代碼產生。如果盒裝intlong要工作,編譯器必須以某種方式確定要使用哪種轉換,但它沒有足夠的信息來執行此操作。請參閱this blog post from Eric Lippert

+2

@Bashir Magomedov:Eric Lippert的博客文章相當不錯,強烈建議你閱讀它。 – R0MANARMY 2010-08-22 14:05:06

+0

@ R0MANARMY謝謝各位!我讀過它了。這是非常全面的。 @svick。謝謝。現在很清楚。 – 2010-08-22 15:02:56

3

(注意:猜猜)

Int32具有轉換運營商Int64這就是得到,當你做的第一投調用。 Object沒有,所以你的第二個演員試圖將一個對象轉換爲另一個不是超類型的類型(Int64不會繼承Int32)。

它與var一起工作的原因很明顯 - 在這種情況下,編譯器只會讓您免於輸入int。使用dynamic時,運行時會執行所有必要的檢查以確定需要執行的操作,而編譯器通常只會插入強制轉換或調用轉換操作符。

5

object擁有一個類型int。但它被認爲是一個對象(它是一個盒裝的int),而且一個盒裝值類型通常只能轉換爲其基礎類型(被裝箱的類型)。

要將其轉換爲其他類型,首先必須將其轉換爲其基礎類型。這工作:

long longNumber2 = (long) (int) intNumber2; 

之所以var作品是編譯器推斷在編譯時的類型。這意味着,當您使用var時,intNumber2(如果您使用typeof)的類型將爲int。而當您使用object時,類型將爲object

使用dynamic是一個完全不同的過程,不能與var進行比較。這裏,轉換/轉換在運行時發生,使用反射和DLR庫。它會動態地找到底層類型,發現它有一個轉換操作符並使用它。

0

您需要取消裝箱到與盒裝相同的類型。

object intNumber2 = 100L; 
// or value in the long type range 
// object intNumber2 = 9223372036854775806; 

long result = (long)intNumber2; 
+1

你也可以將'L'加到號碼上,不需要大數目。 – Abel 2010-08-22 14:06:51

+0

確實!我會在答案中加上這兩種方式。 – 2010-08-22 14:12:10

1

由於是兩種不同類型的強制轉換(一種轉換,另一種拆箱),所以在這裏的答案中已經說明了它不起作用。什麼可能是一個有用的補充,Convert.ToInt64()將轉換任何可以轉換爲長的內置類型或實現IConvertible.ToInt64()的類的類型爲long。換句話說,如果你想能夠將一個包含一個整數(不論大小)的對象轉換爲長整數,那麼Convert.ToInt64()就是要走的路。這是更昂貴的,但你正在試圖做的更昂貴的鑄造,並且差異是可以忽略的(只要足夠大,以避免浪費,如果你知道對象必須是盒裝長)。