欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# null,string.Empty,"",DBNull 的区别

程序员文章站 2022-05-13 21:41:13
【null】 null 在C# 中是一个关键字,表示不引用任何对象的空引用的文字值。 null 是引用类型变量的默认值。 普通值类型不能为 null。 null 在 VS 中定位不出来具体是怎么定义的。一般通过类名映射过来的关键字,都可以定位到声明位置。所以null是比较特殊的。 这个东西要跟踪源头 ......

【null】

null 在c# 中是一个关键字,表示不引用任何对象的空引用的文字值。 null 是引用类型变量的默认值。 普通值类型不能为 null。

null 在 vs 中定位不出来具体是怎么定义的。一般通过类名映射过来的关键字,都可以定位到声明位置。所以null是比较特殊的。

这个东西要跟踪源头还比较麻烦,感觉找不到具体定义。

msdn上说明很简单:null 关键字是表示不引用任何对象的空引用的文字值。 null 是引用类型变量的默认值。 普通值类型不能为 null。

stock overflow 上有一段回答:

there are three things in c# that "null" can be. a reference, a pointer, and a nullable type.

the implementation of c# on the clr represents a null reference by zero bits. (where the number of bits is the appropriate size to be a managed pointer on the particular version of the clr that you're running.)

unsurprisingly, a null pointer is represented the same way. you can demonstrate this in c# by making an unsafe block, making a null pointer to void, and then converting that to intptr, and then converting the intptr to int (or long, on 64 bit systems). sure enough, you'll get zero.

以下翻译(来自google在线翻译):

c#中有三个“null”可以。 引用,指针和可空类型。

clr上的c#实现表示零位的空引用。 (其中位数是适合您正在运行的clr的特定版本上的托管指针的大小。)

不出所料,空指针以相同的方式表示。 您可以在c#中通过创建一个不安全的块,将空指针转换为void,然后将其转换为intptr,然后将intptr转换为int(或64位系统上的long)来证明这一点。 果然,你会得到零。

stack overflow 上的这个回答是基本从比较底层说明的。

那么咱们也从相对比较底层看下c/c++中null的定义。

来自 https://zh.cppreference.com/w/c/types/null 

c:

C# null,string.Empty,"",DBNull 的区别

 

c++ 

C# null,string.Empty,"",DBNull 的区别

 

【string.empty】

这个是 string 类中的一个制度静态变量。也就肯定的说明了 string.empty 是一个存在静态对象。这个就跟 null 区别开了。那到底具体是个什么呢?

string.empty 其实就是 “”。

C# null,string.Empty,"",DBNull 的区别

msdn解释:

C# null,string.Empty,"",DBNull 的区别

 

string.empty 虽然跟 “” 是相等的,但是一般在给 string 初始化为空字符串的时候,一般建议用string.empty,因为“”在赋值给string对象的时候,是你新创建了一个空字符串,而用empty是将你的字符串对象指向了全局的只读的空字符串,这样相对来说性能能优化一些。

 

【“”】

 “” 代表一个空字符串。什么意思,首先是一个字符串对象,但是特殊的是,这个字符串没有内容,这可绝非 null。

 

个人经验简单形容下 null 和 “”。引用类型好比书目录,类对象好比书中内容。如果引用类型不为null,那么目录后面就有页码,如果为null,那么目录后面的页码就为0或者没有页码。那么没有页码,你说这个目录怎么找页数,也就是空引用了。 

 

【dbnull】

 咱先看msdn注解:

dbnull类表示不存在的值。 例如,在数据库中,表的行中的列不可能包含任何数据。 也就是说,列被视为根本不存在,而不是只是不具有值。 一个dbnull对象都表示不存在的列。 此外,com 互操作使用dbnull类,以区分 vt_null 变体,用于指示不存在的值和 vt_empty 变体,用于指示未指定的值。

dbnull类型是一个单一实例类,这意味着只有一个dbnull对象存在。 dbnull.value成员表示单独dbnull对象。 dbnull.value 可用于显式将不存在的值分配到数据库字段中,尽管大多数的 ado.net 数据提供程序自动分配的值dbnull字段没有有效的值。 您可以确定从数据库字段中检索某个值是否dbnull通过将为该字段的值传递值dbnull.value.equals方法。 但是,某些语言和数据库对象提供一些方法,使其更轻松地确定数据库字段的值是否为dbnull.value。 其中包括 visual basicisdbnull函数,convert.isdbnull方法,datatablereader.isdbnull方法,和idatarecord.isdbnull方法。

不要混淆这一概念null在面向对象的编程语言与dbnull对象。 在面向对象的编程语言中,null表示不存在的对象的引用。 dbnull 表示一个未初始化的变量或不存在的数据库列。

 

从上面注解可以看出,dbnull只要用在数据库和com互操作中。而dbnull中有个value字段,这个字段是一个静态只读字段,也就是全局唯一静态dbnull对象,不是null。

当我们在用ado.net操作数据库时,遇到数据库返回字段值为null时,就需要用dbnull来判断,而不能用null来判断。

看看msdn对dbnull.value的注解:

dbnull 是一个单一实例类,这意味着可以存在此类的此实例。

如果数据库字段有缺失数据,则可以使用dbnull.value属性来显式分配dbnull对象的字段的值。 但是,大多数数据访问接口自动执行此操作。

若要评估的数据库字段,以确定它们的值是否dbnull,可以将传递到的字段值dbnull.value.equals方法。 但是,很少使用此方法,因为有多种其他方法来评估缺少数据的数据库字段。 其中包括 visual basicisdbnull函数,convert.isdbnull方法,datatablereader.isdbnull方法,idatarecord.isdbnull方法和其他几种方法。

所以这下就明白了吧,这就是为什么我们用idatareader读取数据库字段信息时,要用dbnull.value来判断是否为空,然后在转换或者其他操作。