为什么Nullable<T>结构能为null

先贴下Nullable<T>简单实现:

[Serializable]
   public struct Nulllable<T> where T : struct
   {
   private Boolean hasValue = false;
   internal T value = default(T);
   public void Nullable(T value)
   {
   this.value = value;
   this.hasValue = true;
   }
   public Boolean HashValue
   {
   get { return this.hasValue; }
   }
   public T Value
   {
   get
   {
   if (!hasValue)
   {
   throw new InvalidCastException("nullable Object mush have a value");
   }
   return value;
   }
   }
   public T GetValueOrDefault()
   {
   return value;
   }
   public T GetValueOrDefault(T defaultValue)
   {
   if (!HashValue)
   return defaultValue;
   return value;
   }
   public override bool Equals(object other)
   {
   if (!HashValue)
   return (other == null);
   if (other == null)
   return false;
   return value.Equals(other);
   }
   public override int GetHashCode()
   {
   if (!HashValue)
   return 0;
   return value.GetHashCode();
   }
   public override string ToString()
   {
   if (!HashValue) return "";
   return value.ToString();
   }
   public static implicit operator Nullable<T>(T value)
   {
   return new Nullable<T>(value);
   }
   public static explicit operator T(Nullable<T> value)
   {
   return value.Value;
   }
 
   }
 }


大家可以看到 public struct Nulllable<T> where T : struct

Nulllable<T>为值类型 同样 T 也为值类型 理论上 Nulllable<T> 不可能跟null扯上关系

那为什么 Nulllable<Int32> temp = null;  那这个null 去那了呢?

下面就通过IL来看看到底发生了什么吧!

第一次:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Nullable<Int32> temp = null;
        }
    }
}
对应的IL:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 代码大小       10 (0xa)
  .maxstack  1
  .locals init ([0] valuetype [mscorlib]System.Nullable`1<int32> temp)
  IL_0000:  nop
  IL_0001:  ldloca.s   temp
  IL_0003:  initobj    valuetype [mscorlib]System.Nullable`1<int32>
  IL_0009:  ret
} // end of method Program::Main

从这里可以看到他这里只是往栈里压了一个 压了一个变量 大家完全可以理解为  Nullable<Int32> temp;

  this.value = 0; 因为default(T)
  this.hasValue = false;

接下来 :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Nullable<Int32> temp = 22;
        }
    }
}
IL:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 代码大小       12 (0xc)
  .maxstack  2
  .locals init ([0] valuetype [mscorlib]System.Nullable`1<int32> temp)
  IL_0000:  nop
  IL_0001:  ldloca.s   temp
  IL_0003:  ldc.i4.s   22
  IL_0005:  call       instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_000a:  nop
  IL_000b:  ret
} // end of method Program::Main

看到了没  区别在:  IL_0005:  call       instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)

他执行了构造函数;

此时:

public void Nullable(T value)
  {
  this.value = value;
  this.hasValue = true;
  }

this.value = 22;

this.hasValue = true;

接下来:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Nullable<Int32> temp = null;
            if (temp == null)
            {
            }
        }
    }
}
IL:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 代码大小       23 (0x17)
  .maxstack  1
  .locals init ([0] valuetype [mscorlib]System.Nullable`1<int32> temp,
           [1] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldloca.s   temp
  IL_0003:  initobj    valuetype [mscorlib]System.Nullable`1<int32>
  IL_0009:  ldloca.s   temp
  IL_000b:  call       instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
  IL_0010:  stloc.1
  IL_0011:  ldloc.1
  IL_0012:  brtrue.s   IL_0016
  IL_0014:  nop
  IL_0015:  nop
  IL_0016:  ret
} // end of method Program::Main

这里的IF执行的是什么呢?

他首先会去检查里面有没有值  IL_000b:  call       instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()

看到这里大家有没有发现这个null那都没用到!没错  其实这里c#编辑器跟我们玩了个魔术 !

看到这里肯定有人会这么写代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Nullable<Int32> temp = new Nullable<Int32>();     
//相当于 Nullable<Int32> temp = null;
            Nullable<Int32> temp1 = new Nullable<Int32>(22);  
//相当于 Nullable<Int32> temp = 22;
        }
    }
}

没错这也是完全正确的!






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值