.Net可空值类型

我们在声明一个对象的时候习惯性把该对象声明为null,但是值类型呢,int需要声明为0,DateTime可以声明为DateTime.Now或者Default(DateTime),那么值类型可不可以声明为null呢?答案是可以的!这就是今天的主题,可空值类型。

可空值类型比较简单,先来看一下可空值类型的语法:

语法:

int? value=3;

上面这句话其实就声明了一个可空值类型value,并给该变量赋值3.

也可以这样写:

int? nullValue = null;

这样就可以给该int类型赋一个null值。

如果说要输出该可空值类型的值,应该怎么做呢?可以这样

 Console.WriteLine(value.Value)

调用该变量的Value属性就可以得到该变量的值。

注意:

可空值类型就这么简单么?是的,它的语法就这么简单,使用起来也很方便,不过有些需要注意的地方,

 static void Main(string[] args)
        {
            int? sum = Sum(23, null);
        }

        public static Int32? Sum(Int32? value, Int32? value1)
        {
            return value + value1;
        }

这段代码的结果是什么?23?不对,结果是null(原因会在下来进行讲解)

以下是一些对可空值类型操作符的定义(来自Clr via c#):


为什么结果是null呢?让我们来剖析一下:

可空值类型内部剖析:

 public static Int32? Sum(Int32? value, Int32? value1)
        {
            return value + value1;
        }

让我们用ildasm来看一下这段代码的方法签名:

.method public hidebysig static valuetype [mscorlib]System.Nullable`1<int32>
        Sum(valuetype [mscorlib]System.Nullable`1<int32> 'value',
            valuetype [mscorlib]System.Nullable`1<int32> value1) cil managed
可以看到Int32?被编译成了Nullable<Int32>结构,

在VS中查看该结构的定义是这样的:

    // Summary:
    //     Represents an object whose underlying type is a value type that can also
    //     be assigned null like a reference type.
    //
    // Type parameters:
    //   T:
    //     The underlying value type of the System.Nullable<T> generic type.
    [Serializable]
    [TypeDependency("System.Collections.Generic.NullableComparer`1")]
    [TypeDependency("System.Collections.Generic.NullableEqualityComparer`1")]
    public struct Nullable<T> where T : struct
    {
        //
        // Summary:
        //     Initializes a new instance of the System.Nullable<T> structure to the specified
        //     value.
        //
        // Parameters:
        //   value:
        //     A value type.
        [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
        public Nullable(T value);

        public static explicit operator T(T? value);
        public static implicit operator T?(T value);

        // Summary:
        //     Gets a value indicating whether the current System.Nullable<T> object has
        //     a value.
        //
        // Returns:
        //     true if the current System.Nullable<T> object has a value; false if the current
        //     System.Nullable<T> object has no value.
        public bool HasValue { get; }
        //
        // Summary:
        //     Gets the value of the current System.Nullable<T> value.
        //
        // Returns:
        //     The value of the current System.Nullable<T> object if the System.Nullable<T>.HasValue
        //     property is true. An exception is thrown if the System.Nullable<T>.HasValue
        //     property is false.
        //
        // Exceptions:
        //   System.InvalidOperationException:
        //     The System.Nullable<T>.HasValue property is false.
        public T Value { get; }

        // Summary:
        //     Indicates whether the current System.Nullable<T> object is equal to a specified
        //     object.
        //
        // Parameters:
        //   other:
        //     An object.
        //
        // Returns:
        //     true if the other parameter is equal to the current System.Nullable<T> object;
        //     otherwise, false. This table describes how equality is defined for the compared
        //     values: Return ValueDescriptiontrueThe System.Nullable<T>.HasValue property
        //     is false, and the other parameter is null. That is, two null values are equal
        //     by definition.-or-The System.Nullable<T>.HasValue property is true, and the
        //     value returned by the System.Nullable<T>.Value property is equal to the other
        //     parameter.falseThe System.Nullable<T>.HasValue property for the current System.Nullable<T>
        //     structure is true, and the other parameter is null.-or-The System.Nullable<T>.HasValue
        //     property for the current System.Nullable<T> structure is false, and the other
        //     parameter is not null.-or-The System.Nullable<T>.HasValue property for the
        //     current System.Nullable<T> structure is true, and the value returned by the
        //     System.Nullable<T>.Value property is not equal to the other parameter.
        public override bool Equals(object other);
        //
        // Summary:
        //     Retrieves the hash code of the object returned by the System.Nullable<T>.Value
        //     property.
        //
        // Returns:
        //     The hash code of the object returned by the System.Nullable<T>.Value property
        //     if the System.Nullable<T>.HasValue property is true, or zero if the System.Nullable<T>.HasValue
        //     property is false.
        public override int GetHashCode();
        //
        // Summary:
        //     Retrieves the value of the current System.Nullable<T> object, or the object's
        //     default value.
        //
        // Returns:
        //     The value of the System.Nullable<T>.Value property if the System.Nullable<T>.HasValue
        //     property is true; otherwise, the default value of the current System.Nullable<T>
        //     object. The type of the default value is the type argument of the current
        //     System.Nullable<T> object, and the value of the default value consists solely
        //     of binary zeroes.
        [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
        public T GetValueOrDefault();
        //
        // Summary:
        //     Retrieves the value of the current System.Nullable<T> object, or the specified
        //     default value.
        //
        // Parameters:
        //   defaultValue:
        //     A value to return if the System.Nullable<T>.HasValue property is false.
        //
        // Returns:
        //     The value of the System.Nullable<T>.Value property if the System.Nullable<T>.HasValue
        //     property is true; otherwise, the defaultValue parameter.
        public T GetValueOrDefault(T defaultValue);
        //
        // Summary:
        //     Returns the text representation of the value of the current System.Nullable<T>
        //     object.
        //
        // Returns:
        //     The text representation of the value of the current System.Nullable<T> object
        //     if the System.Nullable<T>.HasValue property is true, or an empty string ("")
        //     if the System.Nullable<T>.HasValue property is false.
        public override string ToString();
    }

该结构提供了一系列对T进行操作的方法,属性。
上述代码我们也可以这样写:
  static void Main(string[] args)
        {
            Nullable<int> sum = Sum(23, null);
        }
        public static Int32? Sum(Int32? value, Int32? value1)
        {
            return value + value1;
        }

也就是说我们在用int?的时候,编译器实际会把它编译成:Nullable<int>结构,然后对该结构进行操作,该结构重载了对操作符的操作。
装箱和拆箱:
 int? a = 3;
 object o = a;
这段代码会导致a进行装箱。
在装箱的过程中,如果a的Value为null,则将null赋给o,此时不会进行装箱操作,如果a的值不是null,则会对int类型的a进行装箱,并将引用赋给o.
int? b = (int?)o;
在拆箱过程中,如果o指向的引用值为null,则将b和Value赋为null,此时不会发生拆箱操作,如果o指向的引用值不为null,则将o引用的值通过拆箱操作赋给b.
空接合操作符:
有时我们在给一个变量赋值的时候会这样写:
            int? a = 2;
            int? b = a != null ? a : 1;
现在有一种更简单的写法:
int? a = 2;
            int? b = a ?? 1;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值