最近被問到了這個問題,我當時回答是會的,因爲ToString()會把值類型轉換成引用類型,所以會發生裝箱。
後來總覺有些不妥當,所以查閱一些資料並參考網絡上的討論:
拆箱裝箱的官方解釋:
Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type. When the CLR boxes a value type, it wraps the value inside a System.Object and stores it on the managed heap. Unboxing extracts the value type from the object. Boxing is implicit; unboxing is explicit. The concept of boxing and unboxing underlies the C# unified view of the type system in which a value of any type can be treated as an object.
裝箱用於在託管內存中存儲值類型。 裝箱是是值類型到 object 類型或到此值類型所實現的任何接口類型的隱式轉換。 對值類型裝箱會在堆中分配一個對象實例,並將該值複製到新的對象中。
下面是官方的幾個拆箱/裝箱的例子:
eg1: int i = 123; object o = i;//隱式裝箱 eg2: String.Concat("Answer", 42, true) //42和true都會發生裝箱 eg3: List<object> mixedList = new List<object>(); mixedList.Add("First Group:"); for (int j = 1; j < 5; j++) { mixedList.Add(j);//在添加時,j先裝箱 } var sum = 0;for (var j = 1; j < 5; j++) { //下面的一行會發生編譯錯誤: //Operator '*' cannot be applied to operands of type 'object' and 'object'. //sum += mixedList[j] * mixedList[j]); //下面經過拆箱就不會出現上面的編譯錯誤. sum += (int)mixedList[j] * (int)mixedList[j]; }
Note:
相對於簡單的賦值而言,裝箱和取消裝箱過程需要進行大量的計算。 對值類型進行裝箱時,必須分配並構造一個新對象。 取消裝箱所需的強制轉換也需要進行大量的計算,只是程度較輕。
更多性能的瞭解:https://msdn.microsoft.com/zh-cn/library/ms173196.aspx
再引入圖片來在說明內存中的變化:
int i = 123; object o = i;//隱式裝箱
int i = 123; // a value type object o = i; // boxing int j = (int)o; // unboxing
看值類型有沒有進行拆箱,就看他有沒有裝換成Object或者值類型所繼承的接口類型...
Int.ToString 此方法中,值類型轉換成ValueType類型,不滿足裝箱的條件(可以查看下面IL代碼),可以判定Int.ToString是沒有裝箱的。
.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // 代碼大小 45 (0x2d) .maxstack 3 .locals init ([0] int32 v, [1] object o) IL_0000: nop IL_0001: ldc.i4.5 IL_0002: stloc.0 IL_0003: ldloc.0 IL_0004: box [mscorlib]System.Int32 IL_0009: stloc.1 IL_000a: ldloca.s v IL_000c: call instance string [mscorlib]System.Int32::ToString() IL_0011: ldstr "," IL_0016: ldloc.1 IL_0017: unbox.any [mscorlib]System.Int32 IL_001c: box [mscorlib]System.Int32 IL_0021: call string [mscorlib]System.String::Concat(object, object, object) IL_0026: call void [mscorlib]System.Console::WriteLine(string) IL_002b: nop IL_002c: ret } // end of method Program::Main
瞭解了上面的信息之後以後就知道下面建議用哪一個了吧:
int num = 3; //用下面的哪個呢?請思考 string numStr = string.Format("{0}", num); string numStr = string.Format("{0}", num.ToString());
參考:
https://msdn.microsoft.com/en-us/library/yz2be5wk.aspx
http://www.cnblogs.com/DebugLZQ/archive/2012/09/02/2667835.html