您好,登录后才能下订单哦!
最近被问到了这个问题,我当时回答是会的,因为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
http://q.cnblogs.com/q/44027
http://bbs.csdn.net/topics/360191652
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。