views:

3930

answers:

6

I am a little confused about null values and variables in .NET. (VB preferred)

Is there any way to check the "nullness" of ANY given variable regardless of whether it was an object or a value type? Or does my null check have to always anticipate whether it's checking a value type (e.g. System.Integer) or an object?

I guess what I'm looking for is a function that checks all possible kind of null-ness. That is, any type of variables that

a) were never assigned a value since declared

b) were assigned a null value from a data object (that came from a database)

c) were set equals to another variable value which was null

d) were set to an ASP.NET session/application variable that was never set or expired.

Is there a general best-practice when it comes to handling null scenarios in .NET?

Thanks in advance for any feedback!

UPDATE: When I talk about a value type being "null", what I really mean is a value type that was either never set or was at some point set equal to or cast from a null object.

+4  A: 

Value Types can't be null. It violates what it means to be a Value Type. You can wrap Value Types as Nullable(Of T) which gives you a great set of methods, and checks for Nothing do work. But you do have a lot of overhead with that wrapper. Perhaps you can clarify what you're trying to do?

For completeness the VB syntax for Nullable wrappers is:

Dim i as Nullable(Of Integer) = Nothing '.NET 2.0/3.0'
Dim j as Integer? = Nothing '.NET 3.5'

EDIT: Value Type are always preinitialized to a default value, 0 for numerics, false for Booleans, etc.

Bob King
the rule is that for all value types, the default is 0. (int, long, float, double, enums, structs, etc.)
Robert Paulson
A: 

Value type variables can't contain null, that's because what null means, null means that the references points nowhere. I don't know on VB.net but on c# you can wrap value types to be nullables using the "?", like:

int? a = null;
AlbertEin
int? is just a C# compiler shorthand for Nullable<int>.
Robert Paulson
+1  A: 

Is this what you're after?

if IsNothing(foo) OrElse IsDbNull(foo) Then
    ' Do Something Because foo Is Either Nothing or DBNull.Value
End If

In truth I'm not certain why you'd wish for this structure. The Only time I'd check for DBNULL.Value is when I'm using values that came from a database, and before I assign said value from a DATA Namespace class to some other class [i.e. dim b as string = dataReader(0)].

Typically, if you're concerned about an object having not been instantiated, or needing it to be re-instantiated, then just an IsNothing check will suffice.

Stephen Wrighton
+1  A: 

In .Net that are only two types of null that I am aware of, null (nothing in VB) and DbNull. If you are using a System.Nullable, you can use the same null checking syntax as you would with an object. If if your nullable object is boxed the .Net 2.0 CLR is smart enough to figure out the right way to handle this.

The only case I have run into both types is in the data tier of an application where I might be accessing database data directly. For example, I have run into DbNull in a DataTable. To check for both of these null types in this situration, you could write an extension method like (sorry, in C#):

static public bool IsNull(this object obj)
{
    return obj != null && obj != DbNull.Value;
}

...

if(dataTable[0]["MyColumn"].IsNull())
{
  //do something
}
Jason Jackson
A: 

As long as you're developing with Option Strict On, (a) shouldn't be an issue. The compiler will yell at you. If you're worried about checking for parameters, just use

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

For (b), your database interaction layer should handle this. If you're using LINQ, there are ways to handle this. If you're using typed data sets, there an .IsMyVariableNull property on the row that gets auto-generated.

For (c), you don't need to worry about value types, but reference types can be checked with a simple Is Nothing (or IsNot Nothing).

For (d), you can apply the same logic after the read. Test the receiving variable against Nothing.

For the most part, a simple check of Is Nothing will get you by. Your database interaction layer will help you handle the stickier case of null values in your data, but it's up to you to handle them appropriately.

Bob King
+2  A: 

Normal value types (booleans, ints, longs, float, double, enum and structs) are not nullable.

The default value for all value types is 0.

The CLR won't let you access variables unless they have been set. You may think this isn't always the case, but sometimes the CLR steps in and initializes them for you. At a method level you must explicitly initialize all variables before they are used.

Further, as others point out, since .net 2.0 there is a new generic type called Nullable<T>. There are some compiler shorthands in C# like int? means Nullable<int>, double? means Nullable<double> etc.

You can only wrap Nullable<T> over non-nullable value types, which is fine since references already have the ability to be null.

int? x = null;

For an int?, while you can test against null, it's sometimes nicer to call x.HasValue().

In C# there's also the nullable coalescing operator ?? when you want to assign a nullable to a non-nullable value type. But if you don't have the operator, you can call GetValueOrDefault().

int y = x ?? 2; // y becomes 2 if x is null.
int z = x.GetValueOrDefault(2); // same as y
Robert Paulson