當值類型被裝箱時,它被放置在無類型引用對象中。 那麼是什麼原因導致無效的轉換異常呢?CLR如何知道盒裝對象的類型?
long l = 1;
object obj = (object)l;
double d = (double)obj;
當值類型被裝箱時,它被放置在無類型引用對象中。 那麼是什麼原因導致無效的轉換異常呢?CLR如何知道盒裝對象的類型?
long l = 1;
object obj = (object)l;
double d = (double)obj;
不,它不放置在無類型的對象中。對於每個值類型,CLR中都有一個盒裝引用類型。所以你必須東西這樣的:
public class BoxedInt32 // Not the actual name
{
private readonly int value;
public BoxedInt32(int value)
{
this.value = value;
}
}
那盒裝類型不是在C#中直接訪問,雖然它在C++/CLI。顯然,知道原來的類型。所以在C#中,您必須爲該變量提供編譯時類型object
,但這並不意味着這是該對象的實際類型。
查看ECMA CLI spec或CLR via C#瞭解更多詳情。
Jon Skeet的答案涵蓋了爲什麼;至於如何解決這個問題,你需要做的是:
long l = 1;
object obj = (object)l;
double d = (double)(long)obj;
雙重演員的原因是這樣的;當.NET解開變量時,它只知道如何將它裝箱到它的裝箱類型(在你的例子中爲long
)。一旦你拆箱並且你有一個合適的long
原語,然後你可以將它投到double
或來自long
的任何其他類型的澆注料。
野趣,感謝喬恩。 Wagner的Effective C#陳述:「拳擊將一個值類型放入一個無類型的引用對象中」。我很確定它也說了一些大意,即盒裝對象不包含任何類型的元數據,儘管我現在找不到特別的引用。當閱讀那本書時,問題發生在我身上。 – fearofawhackplanet 2010-04-16 10:02:45
@fearofawhackplanet:我不想在Bill的嘴裏說出他確切的意思 - 但是盒子對象絕對*知道它的原始類型,包括枚舉。 (框一個枚舉值,然後直接使用ToString而不拆箱來證明:) – 2010-04-16 10:45:34
我相信一個很好的演示是這樣的。 '長我= 40L;對象o =(對象)l; Console.WriteLine(o.GetType());'在這種情況下,System.Int64被打印到屏幕上。即使'o'是一個對象,底層類型仍然很長。 – 2010-04-16 23:51:28