Nullable<T>、Nullable、null、?修饰符的区别

这章我们讨论一下Nullable<T>、Nullable、null、?修饰符的区别

原创文章

Nullable<T>的前世今生

讨论它们之前,我们有必要讨论一下Nullable<T>的前世今生,目的也是为了让我们更好地了解他们的区别,加深印象。

在C#2以前,有一个问题经常会困扰我们,相信大部分人都想过此问题。

在数据库中,比如设置一个表如下(电脑表Computer)

字段名 类型 是否允许空值
Color varchar Y
Age int N
CpuSpeed int Y
CreateDate DateTime Y
Power int Y

对于Age是int类型,不能允许空值还好说,因为插入数据库时会提示Age要有值才能插入。对于CpuSpeed、CreateDate、Power都是值类型,在程序中不能设置空值,比如int CpuSpeed=null,是不允许的。

那么我们以前是怎么解决这种问题的存在呢?

答:‘给个默认值=空值‘

比如,CreateDate=DateTime.MinValue。表示空值。

这种做法虽然开起来不错,但是显然是在程序设计时要规定好的,容易让人困扰。当新的程序员要接手你的代码时,表示很危险。

那么C#怎么解决这种问题的存在呢?答案就在C#2中引入了Nullable<T>

对于上面的CpuSpeed、CreateDate、Power我们可以在C#中这样来定义:

public Nullable<int> CpuSpeed;

public Nullable<DateTime> CreateDate;

public Nullable<int>Power;

这样,我们就很好的与数据库那边打交道了。

Nullable<T>、Nullable、null、?修饰符的区别

  • Nullable<T>其实就等于?修饰符。比如上面的 public Nullable<int> CpuSpeed;等价于public int? CpuSpeed;
  • 修饰符?是Nullable<T>的简写,请参考上面
  • Nullable<T>是一个结构structs,Nullable是一个静态类。他们结构类型上已经不同。也就是说Nullable<T>是值类型,Nullable是引用类型。

    可以看到源代码:

public struct Nullable<T> where T : struct

public static class Nullable

  • Nullable其实显得有点多余,因为它更多意义上是修饰了Nullable<T>的用法。但是Nullable实现了Nullable<T>很多实用功能。
  • null是表示空值,与Nullable<T>、Nullable没有特别的关联。

null、Nullable<T>

我们有必要说一下null、Nullable<T>的关联。
我们都知道,当比较一个值类型==null时,永远都为false,因为null ‘一般表示引用类型为null‘。
用例子来说明一下把

public class Computer
{
    public string Color;
    public int Age;
    public int? CpuSpeed;
    public DateTime? CreateDate;
    public int? Power;
}
我们来试试比较一下null、Nullable<T>的值是否相等。
第一个需要比较的是,如果Nullable<T>有值时,是否与null的判断,如下:

Computer computer1 = new Computer();

computer1.CpuSpeed = new Nullable();

Console.WriteLine("new Nullable()==new Nullable() " + (computer1.CpuSpeed == new Nullable()));

Console.WriteLine("new Nullable()==null " + (computer1.CpuSpeed == null));

我们首先想想,上面会输出什么呢?

new Nullable<int>()==new Nullable<int>() 肯定是true啦,不用说
new Nullable<int>()==null 按照通常的理解,应该是false,但是这里确实输入true。
为什么呢?哈哈哈,这有点意思呢,我们来看看Nullable<T>的源代码吧:

 public override bool Equals(object other) {
        if (!hasValue) return other == null;
        if (other == null) return false;
        return value.Equals(other);
    }
看第一行,如果没有值并且other为null就返回true。所以我们就明白了为什么新建一个没有值的Nullable<T>时等于null

到此解析结束了。 请转载本文注明转载处与作者。

时间: 2024-11-05 14:39:35

Nullable<T>、Nullable、null、?修饰符的区别的相关文章

C#中override和new修饰符的区别

(new)“隐藏”,(override)“覆盖”(重写).不过要弄清楚这两个有什么区别确实也很难,因为子类在使用父类方法时根本看不出区别,子类不管父类是new了还是override了,用的都是父类方法.区别就在于,一个子类对象中,用父类类型指针去访问子类成员时有区别. 如果是new的,那么父类的这个函数地址仍然保留着,同时又提供了一个新的子类的该函数入口地址.也就是说子类对象中同时保存了两个入口地址,父类的该函数地址被“隐藏”,但是它还可以用父类的类型指针访问得到:用子类类型指针访问该函数,则进

iOS 属性修饰符的区别

前言iOS5 之前 所有的 开发都需要开发者自己控制自己的对象的引用和释放.使用的修饰符是 assign.copy.retain iOS5 之后,Apple 推出了ARC(自动引用计数)机制,推出了新的修饰符替代之前的修饰符 strong.weak 简单说明1:ARC环境下,strong代替retain.weak代替assign2:weak的作用:在ARC环境下,,所有指向这个对象的weak指针都将被置为nil.这个T特性很有用,相信很多开发者都被指针指向已释放的对象所造成的EXC_BAD_AC

java-访问修饰符的区别

说明:所谓访问权限,是指对象是否可以通过"."运算符操作自己的变量或通过"."运算符使用类中的方法. 1.Java中的四种访问修饰符:public.protected.default(无修饰符,默认).private. 2.四种修饰符可修饰的成分(类.方法.成员变量) public protected default private 类 √ × √ ×(内部类可以用private修饰) 方法 √ √ √ √ 成员变量 √ √ √ √ 3.四种修饰符的访问权限 pub

Java学习——public,private,protected等修饰符的区别

public.private.protecte.default是Java里用来定义成员的访问权限的,也就是在成员前不加任何权限修饰符.如: public   class   A{     void   method(){}; } method就属于default权限. 这四个修饰符的访问权限如下表: -----------------------------------------------                         类内部     package内       子类  

private/默认/protected/public权限修饰符的区别

private/默认/protected/public权限修饰符和面向对象的三大特性的封装性有着密切关系.它们都可以修饰类的成员,其中的默认和public还可以修饰类. 类的成员包括:成员变量.成员方法.构造方法.内部类.代码块. 其中: public:修饰类可以被同一项目所有包中的所有类访问(类可见性). 默认:可被同一包中的类访问(包可见性). 小结: 1.内部类属于类的成员,可以使用以上四个修饰符修饰,这一点和类不同. 2.如何使用:类的属性一般使用private修饰,可以通过public

C# const和readonly修饰符的区别

const 的概念就是一个包含不能修改的值的变量.常数表达式是在编译时可被完全计算的表达式.因此不能从一个变量中提取的值来初始化常量.如果 const int a = b+1;b是一个变量,显然不能再编译时就计算出结果,所以常量是不可以用变量来初始化的. readonly 允许把一个字段设置成常量,但可以执行一些运算,可以确定它的初始值.因为 readonly 是在计算时执行的,当然它可以用某些变量初始化.readonly 是实例成员,所以不同的实例可以有不同的常量值,这使readonly更灵活

java成员变量与局部变量修饰符的区别

成员变量: 可以被 public,static ,protected,default,final修饰. 局部变量:包括方法里的和 代码块里的(静态和非静态) 可以被default, final修饰 参考: 百度搜索:代码块与成员变量 java中静态代码块中初始化静态成员变量 分享| 2015-12-31 22:18 ∮老男孩丶 | 浏览 56 次 悬赏:5 javastatic{ age = 2; }static int age = 4; 我把声明age的语句放到代码块后面,为什么没报错,执行代

protobuf的配置原始文件.proto中,使用修饰符repeated、required、optional生成的java文件的区别

最近在做一个基于Netty框架的项目. 该项目使用了Google的Protobuf作为编解码的框架.(没有使用XML或者json是为了更好的提高效率). 经过了一段时间的使用我对Protobuf的原始文件进行一个简单的使用方法总结. 我主要在这里说明一下,原始文件.proto中,修饰符repeated.required.optional的区别. 0.windows环境,java工程 1.安装protobuf后,找到protoc.exe 2.写一个配置文件进行批处理(.bat),如下图所示 3.写

__weak与__block修饰符区别

API Reference对__block变量修饰符的解释,大概意思: 1.__block对象在block中是可以被修改.重新赋值的. 2.__block对象在block中不会被block强引用一次,从而不会出现循环引用问题. API Reference对__weak变量修饰符的解释,大概意思: 使用了__weak修饰符的对象,作用等同于定义为weak的property.自然不会导致循环引用问题,因为苹果文档已经说的很清楚,当原对象没有任何强引用的时候,弱引用指针也会被设置为nil. 因此,__