有些情況下, 值類型的實例需要被視爲引用類型的 實例。對於 這樣的情況下,值 類型實例可通過 過程稱爲裝箱被轉換成一個參考 類型實例。當值 類型實例進行裝箱,倉儲是 在堆上分配和 實例的值複製到該 空間。對該存儲的引用是放置在堆棧上的 。盒裝值 是一個對象, 包含值 類型實例的內容的引用類型。用例在C#中裝箱值類型?
在Wikipedia有針對Java一個例子。但在C#中,有些情況下需要輸入值類型?或者更好/相似的問題是,爲什麼要在堆上(盒裝)而不是堆棧上存儲值類型?
有些情況下, 值類型的實例需要被視爲引用類型的 實例。對於 這樣的情況下,值 類型實例可通過 過程稱爲裝箱被轉換成一個參考 類型實例。當值 類型實例進行裝箱,倉儲是 在堆上分配和 實例的值複製到該 空間。對該存儲的引用是放置在堆棧上的 。盒裝值 是一個對象, 包含值 類型實例的內容的引用類型。用例在C#中裝箱值類型?
在Wikipedia有針對Java一個例子。但在C#中,有些情況下需要輸入值類型?或者更好/相似的問題是,爲什麼要在堆上(盒裝)而不是堆棧上存儲值類型?
一般情況下,你通常會希望避免你的拳擊值類型。
但是,這種情況很少發生,這很有用。例如,如果您需要定位1.1框架,則無法訪問泛型集合。在.NET 1.1中使用集合的任何用途都需要將您的值類型視爲System.Object,從而導致裝箱/取消裝箱。
在.NET 2.0+中仍有這種情況發生。任何時候你想利用包括值類型在內的所有類型都可以直接作爲對象的事實,你可能需要使用裝箱/取消裝箱。這可能有時候很方便,因爲它允許您在集合中保存任何類型(通過在泛型集合中使用對象而不是T),但總的來說,最好避免這種情況,因爲您正在失去類型安全性。然而,經常出現拳擊的一種情況是,當您使用反射時 - 反射中的許多調用在使用值類型時將需要裝箱/取消裝箱,因爲該類型未提前知道。
我認爲在非泛型集合一樣ArrayList發生在C#中拳擊的一個很好的例子。
一個例子是當一個方法接受一個對象參數和值的類型必須傳入。
下面是拳擊的一些例子/拆箱
ArrayList ints = new ArrayList();
myInts.Add(1); // boxing
myInts.Add(2); // boxing
int myInt = (int)ints [0]; // unboxing
Console.Write("Value is {0}", myInt); // boxing
示例!=使用案例 – 2009-11-12 16:01:06
拳擊通常在.NET中自動發生,當他們必須;通常當你將一個值類型傳遞給需要引用類型的東西時。一個常見的例子是string.Format()。將原始值類型傳遞給此方法時,它們將作爲調用的一部分進行裝箱。所以:
int x = 10;
string s = string.Format("The value of x is {0}", x); // x is boxed here
這示出一個簡單的場景,其中一個值類型(x)被自動盒裝要傳遞給需要的對象的方法。一般而言,您希望儘可能避免使用裝箱值類型......但在某些情況下,它非常有用。
有趣的是,當您在.NET中使用泛型時,值類型在用作參數或類型成員時不會被裝箱。這使得泛型比舊的C#代碼(比如ArrayList)更有效,該代碼將{object}視爲類型不可知的。這增加了使用通用集合的另一個理由,如List<T>
或Dictionary<T,K>
,而不是ArrayList
或Hashtable
。
我建議你埃裏克利珀的2的好文章
http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx
這裏是我會100%,
同意使用堆棧當地人報價 類型只是CLR以您的名義執行的優化。 值類型的相關特性是 它們的語義是 被值複製,而不是有時 它們的重新分配可以通過運行時優化 。
在99%的應用程序開發人員不應該關心價值類型堆棧而不是堆中的原因,以及我們在這裏可以獲得的性能增益。伸出心目中非常簡單的規則:
任何規則都允許在特殊情況下排除,但不要試圖過度優化。
p.s. 我遇到了一些具有2 - 3年經驗的ASP.NET開發人員,他們不知道堆棧和堆之間的區別。 :-(我不會僱用這樣的人,如果我是面試官,但不是因爲裝箱/拆箱可以在任何ASP.NET網站是一個瓶頸是我見過。
代碼
int x = 42;
Console.Writeline("The value of x is {0}", x);
實際上箱和unboxes因爲Writeline
做內部的int
演員。爲了避免這種情況,你可以做
int x = 42;
Console.Writeline("The value of x is {0}", x.ToString());
小心微妙的錯誤的!
您可以通過聲明自己的類型爲struct
來聲明自己的值類型。想象一下,你聲明一個struct
有很多屬性,然後在ArrayList
中放置一些實例。這當然包裝了他們。現在通過[]
運算符引用一個,將其轉換爲該類型並設置一個屬性。您只需在副本上設置一個物業。 ArrayList
中的一個仍未修改。
因此,值類型必須始終是不可變的,即使所有成員變量readonly
只能在構造函數中設置,並且沒有任何可變類型作爲成員。
另請參見[boxing-occurrence-in-c-sharp](http://stackoverflow.com/questions/7995606) – nawfal 2013-06-03 08:03:26