C语言基础C#中的BoxingUnboxing
与C++相比,C#中的值类型和引用类型非常简单:所有基本类型、struct和String都属于值类型,其他类型(其实只剩下class)属于引用类型。那么值类型和引用类型有什么区别呢?
值类型赋值时(" = "运算、函数参数、函数返回等。),所有成员变量都将被复制到目标实例中。
引用类型仅在赋值操作期间将实例内存中的地址分配给目标实例。
那么这两者有什么区别呢?
那就是效率:
只要传递一个内存地址,传递的数据量就是32位(64位操作系统是64位)整数。
值类型需要传递它包含的所有数据。
例如:
struct point
{
public int x;
public int y;
}
当分配Point类型的实例时,要传递的数据量是两个整数。
如果数据量较大的结构每次赋值都要传递一次所有成员,那么整个程序运行期间传递的数据量将会非常可观。
如何解决这个效率问题?
考试提示有两种方式:
1使用ref关键字。
2就是用所谓的装箱/拆箱。
首先,装箱/拆箱是针对值类型数据的。对于引用类型来说,它本身就是引用类型,所以没有装箱/拆箱的概念。
其次,Boxing的操作是将值类型的数据赋给object的引用类型实例。这个过程就是赋值的过程(即复制所有数据)。
例如:
点p = newpoint {x = 10,y = 11 };
Object o = p;
这个变量O是装箱后的引用类型。记住,装箱后,变量O与p无关,它们是两种不同类型的变量,指向不同的内存地址。
最后,拆箱的操作就是通过传值的方式将这个对象的引用类型实例赋给目标对象。
例如:
点p2 =(点)o;
拆箱后,p2与o无关,它们是两种不同类型的变量,指向不同的内存地址。
也就是说,装箱/拆箱的目的是为了传输数据。
理解装箱/拆箱也要区别于类类型转换到父类/子类的操作(面向对象语言的继承机制)。
将一个类的实例转换为其父类或子类类型是类的继承机制。实际上,这种转换只是改变了实例的类型信息,实例的数据和内存地址并没有改变。转换前后的实例都指向同一块内存。
但是我们可以统一装箱/拆箱和类继承机制,可以用一句话概括:quote in,quote out价值进,价值出。
0条评论