Nullable Value Type


在.net2.0以前,值类型是不充许赋值为null的,这也是值类型和引用类型的一个重要区别。随着.net2.0的出现,这一局面得以改善,这种功能有点像数据库中的数据类型(int,datetime等),在数据库中列都可以设置是否可为Null。C#实现这种功能主要是依靠一个重要的结构:Nullable<T>,我们先看下它的实现:

[Serializable]
publicstructNullable<T>whereT:struct
{
//
//摘要:
//InitializesanewinstanceoftheSystem.Nullable<T>structuretothespecified
//value.
//
//参数:
//value:
//Avaluetype.
publicNullable(Tvalue);

publicstaticexplicitoperatorT(T?value);
publicstaticimplicitoperatorT?(Tvalue);

//摘要:
//GetsavalueindicatingwhetherthecurrentSystem.Nullable<T>objecthas
//avalue.
//
//返回结果:
//trueifthecurrentSystem.Nullable<T>objecthasavalue;falseifthecurrent
//System.Nullable<T>objecthasnovalue.
publicboolHasValue{get;}
//
//摘要:
//GetsthevalueofthecurrentSystem.Nullable<T>value.
//
//返回结果:
//ThevalueofthecurrentSystem.Nullable<T>objectiftheSystem.Nullable<T>.HasValue
//propertyistrue.AnexceptionisthrowniftheSystem.Nullable<T>.HasValue
//propertyisfalse.
//
//异常:
//System.InvalidOperationException:
//TheSystem.Nullable<T>.HasValuepropertyisfalse.
publicTValue{get;}

//摘要:
//IndicateswhetherthecurrentSystem.Nullable<T>objectisequaltoaspecified
//object.
//
//参数:
//other:
//Anobject.
//
//返回结果:
//trueiftheotherparameterisequaltothecurrentSystem.Nullable<T>object;
//otherwise,false.Thistabledescribeshowequalityisdefinedforthecompared
//values:ReturnValueDescriptiontrueTheSystem.Nullable<T>.HasValueproperty
//isfalse,andtheotherparameterisnull.Thatis,twonullvaluesareequal
//bydefinition.-or-TheSystem.Nullable<T>.HasValuepropertyistrue,and
//thevaluereturnedbytheSystem.Nullable<T>.Valuepropertyisequaltothe
//otherparameter.falseTheSystem.Nullable<T>.HasValuepropertyforthe
//currentSystem.Nullable<T>structureistrue,andtheotherparameteris
//null.-or-TheSystem.Nullable<T>.HasValuepropertyforthecurrentSystem.Nullable<T>
//structureisfalse,andtheotherparameterisnotnull.-or-TheSystem.Nullable<T>.HasValue
//propertyforthecurrentSystem.Nullable<T>structureistrue,andthevalue
//returnedbytheSystem.Nullable<T>.Valuepropertyisnotequaltotheother
//parameter.
publicoverrideboolEquals(objectother);
//
//摘要:
//RetrievesthehashcodeoftheobjectreturnedbytheSystem.Nullable<T>.Value
//property.
//
//返回结果:
//ThehashcodeoftheobjectreturnedbytheSystem.Nullable<T>.Valueproperty
//iftheSystem.Nullable<T>.HasValuepropertyistrue,orzeroiftheSystem.Nullable<T>.HasValue
//propertyisfalse.
publicoverrideintGetHashCode();
//
//摘要:
//RetrievesthevalueofthecurrentSystem.Nullable<T>object,ortheobject's
//defaultvalue.
//
//返回结果:
//ThevalueoftheSystem.Nullable<T>.ValuepropertyiftheSystem.Nullable<T>.HasValue
//propertyistrue;otherwise,thedefaultvalueofthecurrentSystem.Nullable<T>
//object.Thetypeofthedefaultvalueisthetypeargumentofthecurrent
//System.Nullable<T>object,andthevalueofthedefaultvalueconsistssolely
//ofbinaryzeroes.
publicTGetValueOrDefault();
//
//摘要:
//RetrievesthevalueofthecurrentSystem.Nullable<T>object,orthespecified
//defaultvalue.
//
//参数:
//defaultValue:
//AvaluetoreturniftheSystem.Nullable<T>.HasValuepropertyisfalse.
//
//返回结果:
//ThevalueoftheSystem.Nullable<T>.ValuepropertyiftheSystem.Nullable<T>.HasValue
//propertyistrue;otherwise,thedefaultValueparameter.
publicTGetValueOrDefault(TdefaultValue);
//
//摘要:
//ReturnsthetextrepresentationofthevalueofthecurrentSystem.Nullable<T>
//object.
//
//返回结果:
//ThetextrepresentationofthevalueofthecurrentSystem.Nullable<T>object
//iftheSystem.Nullable<T>.HasValuepropertyistrue,oranemptystring("")
//iftheSystem.Nullable<T>.HasValuepropertyisfalse.
publicoverridestringToString();

Nullable<T>数据类型:Nullable<T>能够使C#中的值类型赋值为null,但同时它本身是一个值类型。这个结构的实例比较小,在存储上依然可以存储在堆栈上。

Nullable<int>i=1;
Nullable
<int>j=null;

生成的IL代码足以说明Nullable<T>本身是值类型:

.localsinit([0]valuetype[mscorlib]System.Nullable`1<int32>i,
[
1]valuetype[mscorlib]System.Nullable`1<int32>j)

Nullable<T>的取值,既然能够充许值类型为null,那么如何读取值呢?

第一:Nullable<T>属性
1:HasValue:获取一个值,指示当前的 Nullable<T> 对象是否有值。
2:Value:获取当前的 Nullable<T> 值。如果hasValue等于false,则会抛出异常。

第二:Nullable<T>中包含两个特别重要的方法:
1:T GetValueOrDefault();检索当前 Nullable<T> 对象的值,或该对象的默认值。internal T value=default(T),这个私有字段可以保证返回一个相应类型的默认值。
2:T GetValueOrDefault(T defaultValue);检索当前 Nullable<T> 对象的值或指定的默认值。

Nullable<T>的别名:Nullable<int> 可以写成int?,这是为了方便书写等原因设计。下面的代码是等价的:

int?i=3;//Nullable<int>i=3
int?j=null;//Nullable<int>j=null

Nullable<T>对操作符的影响:

1:一元操作符,如果操作数null,则结果返回null;
2:二元操作符,如果其中一个操作符为null,结果返回null
3:叛等:
1>如果两个操作数都为null,返回true。
2>如果有一个操作数为null,返回false。
3>如果两个操作数都不为null,则比较两个操作数的Value。
4:比较操作符:
1>如果其中一个操作数为null,则返回false。
2>如果两个都不为null,则比较两个操作数的Value。

C#对Nullable<T>的应用:??操作符:如果 ?? 运算符的左操作数非 null,该运算符将返回左操作数,否则返回右操作数。它结合了判断对象是否为空的操作。下面的代码是等价的:可以看出代码简洁不少。

DateTimek=j??DateTime.Now;
DateTimekk
=j==null?DateTime.Now:(DateTime)j;

Nullable Value Type的GetType方法,一个类型申明成Nullable<T>,我们理所当然的认为这个变量的类型会是Nullable<T>,但实际并非我们想象的那样。这里并不会返回Nullable(Int32),而是会返回System.Int32。CLR会直接返回T的类型,而不是Nullable<T>。

Int32?i=1;
i.GetType();

Nullable Value Type对接口方法的影响:我们来看下Nullable<int> 和int在调用IComparable的区别。Nullable<int>并没有实现IComparable接口,但int有实现,所以我样想调用ToCompareTo方法可以这样写(CLR)对Nullable<T>有特殊处理:

Int32?i=1;
Int32iResult
=((IComparable)i).CompareTo(1);

如果没有CLR对Nullable<T>的特殊支持,我们需要这样写,明显可以看出是比较麻烦的方法:

长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn