.NET DBNull vs所有变量类型都没有?
我对.NET中的空值和变量有些困惑。 (首选VB)
是否有任何方法可以检查任何给定变量的"空值",而不管它是对象还是值类型?还是我的null检查必须始终预期它是在检查值类型(例如System.Integer)还是对象?
我猜我在寻找的是一个检查所有可能的空值的函数。也就是说,任何类型的变量
a)自声明以来从未分配过值
b)从数据对象(来自数据库)中分配了一个空值
c)设置为等于另一个为空的变量值
d)设置为从未设置或者未过期的ASP.NET会话/应用程序变量。
在.NET中处理空方案时,是否有一般的最佳实践?
更新:当我谈论一个值类型为" null"时,我真正的意思是一个从未设置过或者在某个时候设置为等于或者从空对象强制转换的值类型。
解决方案
值类型不能为null。它违反了作为值类型的含义。我们可以将值类型包装为Nullable(Of T),这为我们提供了很多方法,并检查Nothing是否起作用。但是该包装确实有很多开销。也许我们可以阐明我们要做什么?
为了完整起见,可空包装程序的VB语法为:
Dim i as Nullable(Of Integer) = Nothing '.NET 2.0/3.0' Dim j as Integer? = Nothing '.NET 3.5'
编辑:值类型总是预先初始化为默认值,对于数字为0,对于布尔值为false,等等。
值类型变量不能包含null,这是因为null表示什么,null表示引用没有指向任何地方。我在VB.net上不知道,但是在c上,我们可以使用"?"将值类型包装为可空值,例如:
int? a = null;
这是你所追求的吗?
if IsNothing(foo) OrElse IsDbNull(foo) Then ' Do Something Because foo Is Either Nothing or DBNull.Value End If
实际上,我不确定我们为什么要使用这种结构。我唯一要检查DBNULL.Value的时间是当我使用来自数据库的值时,以及在将DATA Namespace类的值分配给其他某个类之前[将dim b作为字符串= dataReader(0)]。
通常,如果我们担心某个对象尚未实例化,或者需要重新实例化该对象,则只需执行IsNothing检查即可。
在.Net中,我只知道两种类型的null,即null(在VB中什么也没有)和DbNull。如果使用的是System.Nullable,则可以使用与对象相同的null检查语法。如果将可为空的对象装箱了,那么.Net 2.0 CLR足够聪明,可以找出正确的处理方式。
我遇到这两种类型的唯一情况是在应用程序的数据层中,我可能直接在其中访问数据库数据。例如,我在DataTable中遇到了DbNull。要在这种情况下检查这两种空类型,可以编写一个扩展方法,例如(对不起,在C#中):
static public bool IsNull(this object obj) { return obj != null && obj != DbNull.Value; } ... if(dataTable[0]["MyColumn"].IsNull()) { //do something }
只要使用Option Strict On进行开发,(a)都不是问题。编译器会大吼大叫。如果我们担心检查参数,请使用
Public Sub MySub(ByVal param1 as MyObject, ByVal param2 as Integer) if param1 is nothing then Throw New ArgumentException("param1 cannot be null!") end if 'param2 cannot be null End Sub
对于(b),数据库交互层应处理此问题。如果我们使用的是LINQ,则有多种方法可以处理此问题。如果使用类型化的数据集,则该行上会自动生成一个.IsMyVariableNull属性。
对于(c),我们不必担心值类型,但是可以使用简单的Is Nothing(或者IsNot Nothing)检查引用类型。
对于(d),可以在读取后应用相同的逻辑。针对Nothing测试接收变量。
在大多数情况下,简单地检查"什么都不是"将使我们满意。数据库交互层将处理数据中空值的粘性情况,但这取决于我们如何适当地处理它们。
普通值类型(布尔,整数,长整型,浮点型,双精度型,枚举和结构)不可为空。
所有值类型的默认值为0。
除非已设置变量,否则CLR不允许我们访问变量。我们可能会认为情况并非总是如此,但有时CLR会介入并为我们初始化它们。在方法级别,必须在使用所有变量之前显式初始化它们。
此外,正如其他人指出的那样,自.net 2.0起,就有一个新的泛型类型称为" Nullable <T>"。 Clike int中有一些编译器速记吗?表示Nullable <int>
,是两倍吗?表示Nullable <double>
等。
我们只能将" Nullable <T>"包装在非空值类型上,这很好,因为引用已经可以为空。
int? x = null;
对于int ?,虽然可以测试null,但有时调用x.HasValue()
更好。
在Cthere中,还可以为null的合并运算符??当我们想将可为空的值分配给非可为空的值类型时。但是,如果没有该运算符,则可以调用GetValueOrDefault()。
int y = x ?? 2; // y becomes 2 if x is null. int z = x.GetValueOrDefault(2); // same as y