C# 可空类型详细解析

可空类型的应用范围

         可空类型是为.NET中的值类型设计的,可空类型只能引用值类型变量,不能引用引用类型变量。

         可空类型最常用的是在数据库中,有些整形字段可能不是必填项,这时从数据库中取记录,对于这个为空的整形字段就要非常小心了。而有了可空类型后,就可以很简单的表示。

int age;
if(PersonInfoRow.IsAgeNull()==false)
{
age=int.pravse(personInfoRow.Age.tostring());
}
else
{
age=-1; // 字段为空,需要为变量赋默认值
}

使用可空类型要注意事项

         (1)因为可空类型可能为空,于是很多运算法则将不再简单适用,比如A+B,如果A或者B当中有一个或者两个为可空类型,那么它们便不能简单相加,因为它们可能会为空,这时结果也就可能会为空,所以一定要先使用HasValue属性测试是否为空,或者使用GetValueOrDefault属性返回该基础类型所赋的值或默认值,再或者使用??运算符分配默认值,当前值为空的可空类型被赋值给非空类型时将应用该默认值,比如int?x=null;int y=x??-1;,但是切不可直接进行运算。

         (2)可空类型可以强制转换为对应的基础类型,比如int?x=3;int y=(int)x;,但在转换之前一定要先测试是否不为空,如果为空的话就会出错。

         (3)由于以上两点原因,建议不要随意使用可空类型,只在必要的时候才使用,使用时一定要小心谨慎,随时记得判断是否为空。


可空类型的实现

         Nullable <T> 这个泛型类:

 

[Serializable, StructLayout(LayoutKind.Sequential), TypeDependency("System.Collections.Generic.NullableComparer`1"), TypeDependency("System.Collections.Generic.NullableEqualityComparer`1")] 
public struct Nullable <T> where T: struct 

    private bool hasValue; 
    internal T value; 
    public Nullable(T value) 
    { 
        this.value = value; 
        this.hasValue = true; 
    } 

    public bool HasValue 
    { 
        get 
        { 
            return this.hasValue; 
        } 
    } 
    public T Value 
    { 
        get 
        { 
            if (!this.HasValue) 
            { 
                ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue); 
            } 
            return this.value; 
        } 
    } 
    public T GetValueOrDefault() 
    { 
        return this.value; 
    } 

    public T GetValueOrDefault(T defaultValue) 
    { 
        if (!this.HasValue) 
        { 
            return defaultValue; 
        } 
        return this.value; 
    } 

    public override bool Equals(object other) 
    { 
        if (!this.HasValue) 
        { 
            return (other == null); 
        } 
        if (other == null) 
        { 
            return false; 
        } 
        return this.value.Equals(other); 
    } 

    public override int GetHashCode() 
    { 
        if (!this.HasValue) 
        { 
            return 0; 
        } 
        return this.value.GetHashCode(); 
    } 

    public override string ToString() 
    { 
        if (!this.HasValue) 
        { 
            return ""; 
        } 
        return this.value.ToString(); 
    } 

    public static implicit operator T?(T value) 
    { 
        return new T?(value); 
    } 

    public static explicit operator T(T? value) 
    { 
        return value.Value; 
    } 
}

         可以看到,可空类型为null时,直接使用Value属性时,会产生异常;直接使用ToString方法输出空字符串。这一点和引用类型不一样,引用类型为null时,使用ToString会异常。

int ? m = null;

m.ToString();    // 结果为空字符串

string s = null;

s.ToString();     // 异常

         从这里可以看出,给可空类型变量赋空值时,会调用可空类型的构造函数,实例化一个对象,只不过对象没有指定其内部值。所以此时调用ToString方法是合法的。

         而给引用类型赋空值时,不会调用构造函数,没有实例产生,当然不能调用实例方法。

可空类型从本质上来讲是属于值类型,所以同样可以进行装箱和拆箱操作。

int? notnullable = 5;

int ? nullable = null;

object obj1 = notnullable; // 装箱操作

 notnullable = (int?)obj1; // 可以再进行拆箱操作

int m = (int)obj1; // 可以直接拆箱成内部类型

object obj2 = nullable; // 装箱操作,由于可空类型为空,所以obj2为空

nullable = (int?)obj2; // 可以拆箱成可空类型

m = (int)obj2; // 异常, 因为为空,所以不能拆箱成内部值类型

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值