发文章
发文工具
撰写
网文摘手
文档
视频
思维导图
随笔
相册
原创同步助手
其他工具
图片转文字
文件清理
AI助手
留言交流
在C#1.0版本中,值类型是不允许为NULL的。但有几种方案可由程序员自己实现可空的值类型。
引用类型的空值意味着不引用任何对象。内存中用全零表示NULL,但存储方式上和其他引用无任何差别,即没有多任何一个bit用来标记该引用是否为NULL。这意味全零地址同其他地址一样是一个真实的地址,但不能用于一个真正的引用。但这并不是问题,因为内存地址那么多,完全没必要非要用全零来引用一个活动对象,如果活动对象太多,以至于不得不用全零地址,恐怕内存早就撑爆了。所以引用类型选择牺牲一个潜在的地址,来换取能使用NULL值的便利。
值在概念上只有一个字节构成,可以将0~255存储到那个字节。若超出该范围,读取到的就是垃圾数据。每个值能处理256个“普通”的值,若要再加一个NULL值,就要为每个值类型设置一个额外的标志位,用来判断是真正的值还是NULL。即将值类型改为 1位标志位+7位数据位,则只能表示0~127这128个值。这样,内存的消耗将急剧增大,更不用说每次想要用值类型时,都要检查标志位。所以,对于值类型,选择牺牲NULL值,来换取真正的值的完整的位模式。
但在开发过程中,经常遇到需要使用为NULL的值类型,包括但不限于数据库中日期,整数等都需要使用NULL。在C# 1.0中,解决值类型的可空性,有以下3种方案。
一、魔值: 该方案主要做为DateTime的解决方案,在数据库中,很少有人希望自己的数据中真正的包含某个数据,例如公元1900年01月01日。0时0分0秒。 所以我们可以牺牲一个值(通常是DateTime.MinValue)来表示空值,这个值成为魔值。使用魔值的好处是不用浪费内存,也不用重新构造新的数据类型。但设计不是那么优雅。让人感觉别扭。
二、引用类型包装: 即用object做为变量类型,并根据需要进行拆箱和装箱。复杂一些还可以声明一些隐式转换。该方法允许直接使用NULL,但需在堆上创建对象,频繁使用将会造成垃圾回收困难。
三、值类型包装: 即将一个bool类型的值(用来表示是否为NULL)和一个表示value的值(用来表示真正的值)包装进一个struct值类型。该方案与方案二相似,区别是使用了值类型,从而避免了垃圾回收的问题。缺点是要为每个想处理的类型都创建一个新的可空类型。该方案实际上就是C# 2.0中可空类型的工作方式。
C# 2.0中 引入了System.Nullable<T>和System.Nullable。下面陈述省去域名。
Nullable为一个静态方法类。提供了3个方法Compare<T>,Equals<T>,GetUnderlyingType。这3个方法完全可以由其他类型很好的实现,从而省去这个类,但由于历史遗留问题,该类不能被擦去,从而保留至今。
Nullable<T>是即是可空泛型结构。对该泛型结构的基本用法此处不再赘述。下面仅讨论其在装箱和拆箱时的一些特殊行为。
Nullable<T>是一个struct----一个值类型。这意味着如果把它转换成引用就要对其进行装箱。
Nullable<T>的实例要么装箱成空引用。要么装箱成值类型T的一个已装箱值。永远不可能装箱成一个"装箱的可空值类型T"(即对Nullable<T>装箱后的object),因为不存在该类型。举个例子:int 装箱成obejct后,引用的是int。 那么我们要用可空的int时,构造一个Nullable<int>,然后对其装箱,当其非空时,此处装箱为对一个普通int值类型进行装箱的结果,而不是装箱为对一个可空int值类型Nullable<int>进行装箱的结果。当其为空的时候,则装箱成空引用,即上文提到的引用全零地址。
已装箱的值可以拆箱成普通类型,或者对应的可空类型。拆箱一个空引用时,如果拆箱成普通类型,则会抛出一个NullReferenceException;但如果拆箱成恰当的可空类型,就会拆箱成没有值的一个可空类型的实例。
来自: 昵称10504424 > 《C#》
0条评论
发表
请遵守用户 评论公约
pojo中用基本类型还是用对象
pojo中用基本类型还是用对象我的选择是包装类好!所有的sql使用的默认类型都是null,如果你把POJO中的映射属性类型写为基本类型,当查找不到记录的时候,返回null赋给基本类型就会出错 2。包装类型都可...
可空类型
可空类型。所要做的只是在类型声明后面加上一个?号:int?number;之后,便可以放心地将空值赋给它了:number=null;可空类型可以表示其基础值类型正常范围内的值,再加上一个null值。在不想使用泛型的写法来...
c#声明变量加问号(?)的区别 DateTime StartTime和DateTime? ...
c#声明变量加问号(?)的区别 DateTime StartTime和DateTime?它可以通过对包装类型直接赋值的方式隐式创建,如:int? a=32;表示该变量可以为null,如:int? i=null;而不带问号 int i=0;(不能让i=null...
private DateTime?
因此,当把一个可空类型值赋给一个非空类型时,将引发编译错误,例如:int? ni = null;int i = ni; //这一句将引发编译错误 推荐的方法是赋值前对可空类型的值进行检查,在C#中使用??运算符分配默认值...
C#中的可空类型运算(Nullable<T>)------T?
可使用 null 关键字将可以为 null 的类型的变量设置为 null,如以下示例所示:在对可以为 null 的类型执行比较时,如果其中一个可以为 n...
int?
Nullable 结构支持将值类型扩展为可以为null,但不支持在引用类型上使用,因为引用类型本身就是可空的。可空类型表示可被赋值为 null 值的值类型变量。如果基础类型的值为 null,请使用 System.Nullabl...
关于指针变量在内存中所在的长度(转载)
关于指针变量在内存中所在的长度(转载)关于指针变量在内存中所在的长度(转载)作者:又是一年夏天 | 出处:博客园 | 2011/6/24 14:27:15 | 阅读9次。void指针一般称为“通用指针”或“泛指针”。之所以...
有了《C语言其实很简单》再不用惧怕指正!
然而地址是不能被保存在普通变量中的,C语言提供有一种特殊的专有变量专门用来保存地址,这种变量称为指针变量,指针变量也可简称为指针...
周立功:安全有效地使用C掌握指针—声明与访问
既然&iNum是指向变量iNum的指针,那么存放指针&iNum的变量就是“指针变量”。虽然指针&iNum是指内存地址本身,指针变量ptr是指存储内存地址的变量,但两者之间的区别并不重要。null指针和...
微信扫码,在手机上查看选中内容