打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
带着问题读CLR via C#(三)基元类型,引用类型和值类型(上)

带着问题读CLR via C#(三)基元类型,引用类型和值类型(上)

Q1: 什么是基元类型?C#中有哪些基元类型?

A1: 编译器能直接支持的数据类型称为基元类型,基元类型直接映射到FCL中存在的类型,比如C#中int映射到System.Int32类型。

C#中的基元类型:

我们可以定义这样定义一个字符串:

String str = "abc";

也可以这样定义一个字符串:

string str = "abc";

它们生成的IL是完全相同的,string可以被C#编译器直接映射到FCL中的System.String类型,换言之,C#编译器自动假定所有的源代码中都添加了这个命令:

using string = System.String;

类似的int和Int32, double和Double也都是一样的。

 

Q2: 什么是值类型,什么是引用类型,它们的区别是什么?

A3: 派生自System.ValueType的类型称为值类型,值类型可以实现一个或多个接口,但不能作为其他类型的基类。值类型的内存空间分配在线程栈中,在代表值类型的一个实例的变量中,并不包含指针,而是包含了实例本身的字段,值类型的实例不受垃圾回收器的控制。引用类型的内存空间分配在托管堆中,它的实例由垃圾回收器进行回收,在线程栈中存储的实例变量只包含一个指向托管堆中特定位置的一个指针。

 

Q3: 分析以下代码。

A3:

 

Q4: 何时使用struct, 何时使用class?

A4: 同时满足以下三个条件:1)类型中没有成员会会修改类型的实例字段;2)类型不需要从其它任何类型继承;3)类型不会派生出其他任何类型;并满足以下两个条件中的一个:1)类型的实例小于16字节;2)类型的实例大于16字节,但不作为方法的实参传递,也不作为方法的返回值。此时,可以把这个类型定义为struct, 否则定义为class.

 

Q5: 定义一个值类型应该注意什么?

A5: 1)由于System.ValueType重写了Equals方法和GetHashCode方法,在定义自己的值类型时,也要重写这两个方法并提供它们的显式实现;2)所有方法都不能是虚方法。

 

Q6: SomeVal为一个struct,包含一个实例字段x, 以下代码有何不同?

A6: 两行代码都会在线程栈上分配内存空间,唯一的不同在于C#会认为new操作符对v进行了初始化。如果用第一行代码定义v, 打印v.x时会打印出默认值0, 如果使用第二行代码定义v, 打印v.x时会出错。

 

Q7: 什么是装箱和拆箱,装箱和拆箱的过程是什么?

A7: 值类型转换为引用类型会发生装箱。装箱的时候,首先会在托管堆中分配内存空间,这包括值类型各个字段需要的内存空间加上托管堆上所有对象都有的两个成员(类型对象指针和同步块索引);然后会将值类型的字段复制到托管堆上;最后返回对象的地址。引用类型转换为值类型会发生拆箱,拆箱操作并不是装箱操作的逆操作,拆箱其实是获取一个指针的过程,该指针指向已装箱实例的未装箱部分,紧接着会发生一次复制操作。

 

Q8: 分析以下代码,判断三次打印各发生了多少次装箱和拆箱。

A8: 第一次打印发生了三次装箱(Int32类型的v转换为Object类型的o, Int32类型的v转换为字符串,o被转换为Int32发生拆箱,再被转换为字符串,发生装箱);第二次打印发生两次装箱(Int32类型的v转换为Object类型的o, Int32类型的v转换为字符串);第三次打印只发生了一次装箱(Int32类型的v转换为Object类型的o)。

 

Q9: 以下代码是否正确?

A9: 不对。当一个对象进行拆箱操作时,只能转换为它原先未装箱时的值类型,故应该为:

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
C# 值类型与引用类型 (上)
CLR via C#:基元类型 引用类型和值类型
初读CLR Via C# 之
C# 线程安全及线程同步技术
C#的引用类型在内存到底是怎么分配的
C#中的运行时与编译时类型
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服