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 Article With Your Friends!

We use cookies to give you the best experience possible. By continuing, we'll assume you're cool with our cookie policy.

Install Love2Dev for quick, easy access from your homescreen or start menu.

Googles Ads Bing Pixel LinkedIn Pixel