为了让。网中的值类型可以赋值为null,微软特地添加了NullableT类型,也可简写为t?但是NullableT自身是结构体,也是值类型,那么它是如何实现将空赋值给值类型的呢?
下面通过自定义一个可空值类型来讲解NullableT的实现原理。
自定义可空值类型
结构XfhNullableT,其中T :结构{私有T innerValue//这个属性很重要公共bool HasValue { set得到;}公共T Value { get { return HasValue?内部值:引发新的无效的operation exception();} } public XfhNullable(T值){ this . innervalue=valueHasValue=true }公共T GetValueOrDefault(T值){返回HasValue?this.innerValue:值;} public T GetValueOrDefault(){返回此。innervalue}}一个可空值类型的结构体大致功能已经定义好了,下面我们来创建可空值类型的实例来验证下。
使用静态系统。控制台;类程序{静态void Main() { //使用结构体默认的无参构造函数进行实例化XfhNullableint num=new XfhNullableint();写线(数量.有价值);写线(null_num .GetValueOrDefault());} }
可以看到,变量数字并不含有值,调用GetValueOrDefault()则会获取它的默认值0;
这时我们将空赋值给变量数字会发现编译器报错无法将空转换为“XfhNullableint”,因为它是不可为空的值类型这是因为编译器把我们定义的结构体XfhNullableT看作是普通值类型而非可空值类型,所以我们还要添加可空值类型和XfhNullableT之间的转换功能。
公共静态隐式运算符XfhNullableT(T?nullable value){ if(nullable value==null){ 0返回新的xfhNullAbleT();}返回新的xfhnullable t(NullAbleValue .价值);}上面的代码实现了可空值类型向XfhNullableT的隐式转换,添加上面代码之后发现编译器不再报错XfhNullableT。已经成为一个可为空的值类型。
静态void Main(){ XfhNullableint null _ num=null;写线(null_num .有价值);}
XfhNullableT中的属性哈希值的作用就是标记当前类型是否为null,若是则返回假的,否则返回没错。当哈希值为错误的时调用该类型的价值属性则会抛出异常无效操作异常。但可调用GetValueOrDefault()方法来获取类型的默认值。
NullableT类型可以通过运算符==来判断值是否为null,我们也可以通过运算符重载来实现该功能:
公共静态弯曲件运算符==(XfhNullableT cn,object obj){ if (cn .HasValue){ return false;}返回真}公共静态弯曲件运算符!=(XfhNullableT cn,object obj){ return!(cn==obj);} static void Main(){ XfhNullableint null _ num=null;写行(null _ num==null);}
接下来,我们来实现普通值类型和XfhNullableT之间的转换:
公共静态隐式运算符XfhNullableT(T值){返回新的XfhNullableT(值);}公共静态显式运算符T(XfhNullableT值){返回值. innervalue } static void Main(){ XfhNullableint null _ num=null;null _ num=12//int类型隐式转换为XfhNullableint类型写行(null _ num==null);写线(null_num .价值);int I=(int)null _ num;//XfhNullableint类型强制转换为(同国际组织)国际组织类型写行(I);}
获取实例在运行时的类型:
静态void Main(){ XfhNullableint null _ num=12;写线(null_num .GetType());}
这个返回值不大友好,我们希望这里返回内置的值类型,系统Int32,具体实现代码如下:
//因为目标类中的GetType方法不允许子类重写(避免子类隐藏自己的实际类型)//所以这里使用关键字新的来隐藏目标类中的GetType方法公共新类型GetType(){ 0返回内在价值.GetType();}
结论:没有可为空的值类型
此时,我们已经定义了一个可空值类型XfhNullableT。通过上面的代码,我们很容易发现可空值类型不存在。它通过属性HasValue标记空值,并通过字段innerValue(对应于NullableT中的value字段)维护该类型的值。如果赋值为null,则innerValue被初始化为值类型的初始值。换句话说,NullableT只在逻辑层面上给值类型赋null,给我们一种值类型可以为null的感觉。
最后,我们将讨论可空值类型的打包和解包。
CLR在装箱时首先检查NullableT实例是否为空。如果是这样,CLR不装箱任何东西,而是直接返回null。如果实例的值不为空,则获取实例的值(值属性)并将该值装箱。
解包时,为空值返回一个NullableT()实例,为特定值(如5)返回一个NullableT(5)实例。
以上就是本文的全部内容。希望本文的内容能给大家的学习或工作带来一些帮助,也希望多多支持我们!