C# null和System.DBNull.Value之间有什么区别?

C# null和System.DBNull.Value之间有什么区别?,c#,null,dbnull,C#,Null,Dbnull,null和System.DBNull.Value之间有什么区别吗?如果是,是什么 我现在注意到了这种行为- while (rdr.Read()) { if (rdr["Id"] != null) //if (rdr["Id"] != System.DBNull.Value) { int x = Convert.ToInt32(rdr["Id"]); } } 虽然我使用sql datareader从数据库中检索数据,但是如果(rdr[“Id”!=nul

null和System.DBNull.Value之间有什么区别吗?如果是,是什么

我现在注意到了这种行为-

while (rdr.Read())
{
    if (rdr["Id"] != null) //if (rdr["Id"] != System.DBNull.Value)  
    {
        int x = Convert.ToInt32(rdr["Id"]);
    }
}
虽然我使用sql datareader从数据库中检索数据,但是如果(rdr[“Id”!=null)没有返回值
if
返回
true
,并最终抛出将null转换为整数的异常

但是,如果我使用
if(rdr[“Id”!=System.DBNull.Value)
返回
false


null和System.DBNull.Value之间有什么区别

DBNull.Value是.NET数据库提供程序返回的值,表示数据库中的空条目。DBNull.Value不为null,并且对于从数据库行检索到的列值,将其与null进行比较将不起作用,您应该始终与DBNull.Value进行比较


嗯,
null
不是任何类型的实例。相反,它是一个无效的引用

但是,
System.DbNull.Value
是对
System.DbNull
实例的有效引用(
System.DbNull
是一个单例,
System.DbNull.Value
提供对该类的单个实例的引用),该实例表示数据库中不存在的*值

*我们通常会说
null
,但我不想混淆这个问题

所以,两者在概念上有很大的区别。关键字
null
表示无效引用。类
System.DbNull
表示数据库字段中不存在的值。一般来说,我们应该尽量避免使用相同的东西(在本例中为
null
)来表示两个非常不同的概念(在本例中为无效引用,而不是数据库字段中不存在的值)


请记住,这就是为什么很多人提倡通常使用,这正是
系统的一个例子。DbNull
就是一个例子。

DataRow有一个名为
IsNull()
的方法,您可以使用该方法来测试列是否有空值-关于数据库看到的空值

DataRow[“col”]==null
将始终为
false

使用


相反。

Null类似于C++中的零指针。因此,它是一个不指向任何值的引用


DBNull.Value
完全不同,是一个常量,当字段值包含NULL时返回。

来自以下文档:

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


必须处理的DBNull.Value很烦人

我使用静态方法检查它是否为DBNull,然后返回值

SqlDataReader r = ...;
String firstName = getString(r[COL_Firstname]);

private static String getString(Object o) {
   if (o == DBNull.Value) return null;
   return (String) o;
}
另外,在将值插入数据行时,不能使用“null”,必须使用DBNull.Value


“null”有两个表示形式是一个糟糕的设计,没有明显的好处。

嗯,它们是不相关的。一个是
System.Data
中类的静态实例,另一个是表示缺少引用的特殊值。他们彼此无关。你能详细说明你对什么感到困惑吗?你真正的问题是“为什么
DataRows
DataReaders
DBNull.Value
放在它们自己内部而不是
null
?”嗯,我的问题不是最初的问题,但从你说的话中学习之后,我很好奇。你能告诉我为什么DataRows和DataReader将DBNull.Value放在它们自己而不是null中吗?我自己也不确定。这里有一个答案:也有可能在C#中出现可空值类型之前,处理
null
会更麻烦。我在这里有一个答案,但我意识到它更适合-所以我移动了itp.s。还应使用DBNull.Value将null参数传递给数据库,否则可能会将其解释为未传递参数。DBNull不是“数据库返回的内容”-它只是ADO.NET选择的解释方式;就我个人而言,我不确定这种解释是否非常正确valuable@MarcGravell是的,马克,你说得对。我用词不对。ASP.NET将数据库null列值转换为DBNull.value+1一个实际示例:如果使用
IDbCommand.ExecuteScalar()
,它可以返回null(未返回任何记录)或
DBNull
(第一条记录中的第一列是“不存在的值”)。如果没有
DbNull
您将无法区分两者。我强烈建议您使用一种禁止使用Null的语言,并且这样做的成本绝对为零。生命对于“空对象模式”来说太短,空引用是完全有效的。☺@当然,还有另一个常见的建议:函数应该只返回一种类型的值。这就是为什么人们更喜欢类型良好的打字脚本代码。“执行状态”与“计算结果”不同。他们可能已经决定以其他方式实现此功能(可能是一个out参数,或者类似于HTTP请求-响应objs的对象)。当然,这不是一个真正想要的复杂问题,但如果他们这样做了,也许可以使用null来代替DbNull。我们共同的厌恶情绪是:你的上一句话只是被出现在这里阅读这篇文章并发现你的用户名是“讨厌”的讽刺所压倒
SqlDataReader r = ...;
String firstName = getString(r[COL_Firstname]);

private static String getString(Object o) {
   if (o == DBNull.Value) return null;
   return (String) o;
}