装箱和拆箱的易错点整理总结

.Net中装箱和拆箱操作,以及相关所做的事情大家应该是众所周知的事情,这里就截取书上的一些概念细节

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 如果要在代码中显式的判断装箱后的引用类型的原始类型,可以 使用 is操作符判断  或者通过GetType()方法判断

if(  o  is  Int32)  o.GetType()

 

关注装箱和拆箱操作,关键的地方还是在性能问题上。正如上面解释的,装拆箱操作会涉及到给值类型堆空间分配,会涉及到复制值,还会有一些额外的无类型的变量,给GC带来一定的负担,所以我们应该避免装拆箱操作,特别的泛型是最常用的一种去减少装拆箱的方案。现在我们关注的是如果涉及到了的情况,一般我们可以写代码 让值类型变成引用类型,这种是显式的,还有一种是代码隐式的,  特别在一些调方法传参的时候做的一些隐式的类型转换,如果在一个循环下的话,性能问题就凸显出来了,比如最常见的 ArrayList(Array的一个复杂版本,支持动态添加,内部维护了一个Object的数组),和HashTable 。

 

 

 

再一个典型例子:

 

 

 还有一种是枚举

枚举可以被装箱成System.Object,System.ValueType.和System.Enum,以及System.Enum实现的三个接口类型System.Icomparable,System.IConvertible,System.Iformattable

 

 

这是个例子: 

 

 

 再比如:

 GetType方法是由System.Object类型提供的,因此值类型调用的时候必须执行相应的装箱操作,而Object提供了几个虚方法,包括 ToString(),Equal(),GetHashCode(),Finalize(),这些有些值类型是进行重写了的,比如int32重写了ToString(),因此不会执行装箱操作

 

这里你就会疑问,为什么 int和 enum 定义的枚举都是值类型,一个前者没有装箱,后者缺装箱了,这个我们可以从继承上挖一下

其中int 对应的是Int32,是一个结构类型,他调的重写方法是int32下的方法

 

 而枚举类型 就不是了,他直接定义的是Enum下的,这里重写了ToString(), 可以看出Enum是个引用类型,所以装箱了,

 

 这里我们就引出了 enum 和Enum到底是不是一个东西,显然不是。

enum是一个c#关键字,是c/c++/c#等c语系语言一种关键字.用于定义枚举类型.

我们定义枚举类型的格式是 

enum <enum_name> {enumeration list};

枚举类型都是值类型,所有枚举类型都隐式地继承 System.Enum 类型,当然也同时继承了它的所有成员, System.Enum 类型是继承自 System.ValueType 类型唯一不为值类型的引用类型;System.Enum是一个抽象类(abstract class)

所有的值类型都是System.ValueType的后代,枚举类型也不例外,枚举类型直接继承自System.Enum,而System.Enum却又直接继承自System.ValueType的,所以,枚举类型也是System.ValueType的后代。
值类型都是System.ValueType的后代”,但System.ValueType的后代不全是值类型,System.Enum就是唯一的特例!

在System.ValueType的所有后代中,除了System.Enum之外其它都是值类型.

当然还有各种形形色色的装箱和拆箱例子,后期遇到新奇的,再一一收纳。其中看IL代码是最为直接的

 

posted @ 2020-08-06 00:41  凯帝农垦  阅读(254)  评论(0编辑  收藏  举报