Welcome to Professional ASP.NET - Chris Love's Official Blog Sign in | Join | Help

Chris Love's Official ASP.NET Blog

Chris Love's Helpful tips, tricks and pragmatic development knowledge for the ASP.NET world.
Add to Technorati Favorites


ASP Insider Follow Me On Twitter
Doing Nothing in .NET

Dealing with Null values (nothing in VB.NET) is a common problem for programmers of any stripe. Null dates stored in the database seem to be a common issue developers experience when they start dealing with null values. Null values in the database for a value type poses a problem in the application. The .NET framework provides Nullable Types, a Coalesce operator in C# and If in VB.NET that can help the situation.

I am going to discuss several features of the .NET framework, SQL Server and the CSLA framework that .NET application developers should know about so they can appropriately solve the null value issue.

Value Types

A value type is a fundamental element of a language, such as an integer, character, boolean, datetime or byte. These types cannot be set to null.

C#:

int x = null;  //Not allowed, compiler error.

VB.NET:

Dim x as Integer = nothing ‘Not allowed, compiler error.

If you think about it, this rule makes sense because these are the fundamental building blocks of any application. Allowing them to be null could cause major ramifications. Object types, such as classes, can be null because they serve a different purpose and would typically ‘hold’ value types.

Nullable Types

Value types can be modified at declaration to be Nullable Value Types by appending a ? to the end of the type, int? (C#) or Integer? (VB) for example. This makes the value type able to be set to null. A Nullable value type’s value cannot be set to a normal value type, even if it has a real value.

C#:

int? x = null;

int y = x; //Causes a compiler error.

VB.NET:

Dim x as Integer? = nothing

Dim y as Integer = x ‘Throws a compiler error because it cannot be cast.

When the value type is compiled to IL it creates a System.Nullable<T> (C#) or System.Nullable(of T) (VB.NET).

Coalesce

Fortunately there is the concept of Coalesce in both C# and VB.NET. I blogged about using Coalesce in transact SQL in September of 2007. Coalescing a value type is the act of checking a value for a null value and defining a default value if it is null. I recommend any select statements including fields that allow null values be wrapped in a COALESCE function to be safe.

In C# coalescing is done using the Null Coalescing Operator, ??, where a variable’s value will be assigned if it is not null, otherwise the default value will be used. The default value is declared to the right of the ?? operator, e.g. variable ?? [default value].

int? x = null;
int y = x ?? 5; //This works because if x is null, y will be set to 5.

In VB declaring a nullable type and using coalesce is an if statement with the potentially null value separated by a comma from a default value.

Dim x As Integer? = Nothing
Dim y = If(x, 5) ‘This works because if x is null, y will be set to 5.

Alternatives to Manage Null Value Types

There are alternatives to using coalesce to provide default values for a potentially null value; ternary if (C#) and IIF (VB.NET) have been used by many programmers over the years. This is a common practice when a value is set from a database field, and there is no control over the value being retrieved, since a database field can hold null values. I am starting to oppose allowing null values in a database field if it can be avoided, simply because managing potentially null values has caused so many headaches for developers over the years.

In the C family of languages, the ternary if statement has been a staple. If a conditional is true the first value is returned, otherwise the second value is returned. The syntax is if ([conditional]) ? a : b;

static int Square(int a){

return if (a != null) ? a * a : 0;

}

Similarly the VB family has had the IIF function, which serves the same purpose. It seems to be heading towards deprecation and should be replaced with the If(x,y) syntax highlighted earlier.

Public Shared Function Square(a as Integer) as Integer

      return IIF(not a is nothing, a * a, 0)

End Function

At the urging of Bill McCarthy I do want to point out that IIF is a function of the VB language. Each parameter in the expression is evaluated and almost useless.

CSLA’s Answers for Working with Null Value Types

While I do not use the CSLA framework in my day to day life, I study it as much as I can. Rocky Lhotka does a fantastic job of using every ounce of the .NET framework and language in the CSLA framework. If you take time to study CSLA you will find very obscure language features being used in their proper context. I also find many of these features sparsely documented in the wild, which makes finding real world uses of them hard.

I first starting using pieces of the framework when I discovered the SmartDate class about 2 years ago. This is a class that wraps around the DateTime value type. The SmartDate class sets a default value, either MinValue or MaxValue for a null datetime value. To me, this means I store the MinValue of a datetime in the database when I have an optional date value that has not been supplied by the user through the user interface.

It has been a lifesaver for me to have a consistent class to manage dates, and thus reduces the amount of code I need to manage and maintain on live applications. It is a class instead of a value type, and actually wraps the value type in a protective layer of sorts to insulate the application from having a null value type to process.

The second class I really like is the SafeDataReader. The SafeDataReader implements the IDataReader interface, therefore it is a commonly used interface. It does need a helper method to ‘convert’ a SQLDataReader to a SafeDataReader. A wrapper method around any ExecuteReader method could return a SafeDataReader as well.

The class ‘fixes’ any null values before they are returned to the business code. This makes calling the GetXXX methods, such as GetString much safer than the typical DataReader class. In my opinion Rocky did it right, not the framework classes. For example this is the GetString method of the SafeDataReader class. It checks the value returned from the database for DBNull, and if it is, it sets the value to an empty string.

The GetString method from the CSLA class:

Public Overridable Function GetString(ByVal i As Integer) As String _
  Implements IDataReader.GetString

  If _dataReader.IsDBNull(i) Then
    Return ""
  Else
    Return _dataReader.GetString(i)
  End If
End Function

The standard GetString method on the framework’s DataReader classes allows null values to be returned because the database can allow null values in a field. This is a disconnect from how we should process data values, which the SafeDataReader addresses.

Conclusion

The .NET framework and family of languages have several options available for developers to work with null values in a safe way. There are also alternatives available in many of the publicly available code bases, such as CSLA.

Nullable types are declared using the ? modifier and are the first line of defense, but they require prior knowledge as to what values could be null. Traditional method use the ternary if and IIF constructs. So there should be no reason why any .NET developer says they are struggling with null values in the application. NullReferenceExceptions should be a thing of the past for .NET applications with this knowledge.

References:

http://visualstudiomagazine.com/columns/article.aspx?editorialsid=2297

http://www.dnrtv.com/default.aspx?showNum=97

http://www.dnrtv.com/default.aspx?showNum=98

http://rocksthoughts.com/blog/archive/2008/03/26/vb.net-true-ternary-operator-if.aspx

Share this post :
Posted: Sunday, July 13, 2008 10:32 PM

by Chris Love
Filed under: , ,

Comments

Walt Ritscher said:

Actually you can assign Nothing to a value type in VB. When assigned to a value type it uses the default value (usually 0). The following compiles and runs. Dim x As Integer x = 6 x = Nothing ' x is 0 Console.WriteLine(x) Dim y as Boolean y = True y = Nothing ' y is False Whether this make for readable code is another question however. The benefit of Nullable (Of T) is that it remembers that you stored a null value within where the above example changes from Nothing to default value.
# July 14, 2008 2:59 AM

David Keaveny said:

CSLA's approach sounds like an implementation of the Null Object pattern.
# July 14, 2008 3:00 AM

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# July 14, 2008 4:35 AM

Chris Love said:

Actually you should get a compiler error. I run Option Explicit On and Option Strict On, so maybe that is why I do get a compiler error. If you try to run the application you would get an InvalidOperationException, "Nullable object must have a value."

# July 14, 2008 4:57 AM

TrackBack said:

# July 15, 2008 9:09 PM

Speednet said:

Chris, Great post, thanks! I *always* run with both Strict and Explicit ON. I do not get a complier error assigning Nothing to a value type. You can see this another way: from the perspective of a Structure. Structures cannot take initial value assignments in their definition, so all values are initially assigned their "Nothing" value, which is their default value. The following exmaple generates a complier error, because Structures cannot have initial value assignments. Structure MyStruct Public i As Integer = 1 End Structure The proper syntax is as follows, which assigns Nothing to i, which is 0 [zero] for an Integer type. Structure MyStruct Public i As Integer End Structure Structures are by definition Value types, so the Nothing assignment MUST be OK by the same token. -Todd
# July 16, 2008 12:20 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS