Click here to Skip to main content
Licence 
First Posted 7 Nov 2004
Views 75,496
Bookmarked 26 times

NullSafe Functions: Ensuring Safe Variables

By | 7 Nov 2004 | Article
In this article Rob Walling offers some functions that ensure variables returned from DataSets, ViewState, Session State, or Functions won't break your code.

Introduction

Values retrieved from DataSets, ViewState, Session State, or any number of other storage mechanisms can cause errors if they comes back as DBNull or Nothing. As an example, let's say you want to retrieve a String from a DataSet. Typically, you begin by checking if the value is DBNull.Value, then casting the value to a String (if you code with Option Strict On), then checking if it's Nothing, then trimming it. A similar process applies when retrieving a String from ViewState and Session State:

Dim firstName as string
' Check for DBNull
If ds.Tables(0).Rows("FirstName") is DBNull.Value Then
    firstName = String.Empty
Else
    firstName = CStr(ds.Tables(0).Rows("FirstName"))
    ' Check for Nothing
    If Not IsNothing(firstName) Then
        firstName = firstName.Trim
    End If
End If
' Now you can safely work with the value...

To overcome this cumbersome and repetitive process, I've created several "NullSafe" functions that handle the casting, trimming, and safety-checking of values.

Making Strings NullSafe

The first function is called NullSafeString. Notice that if the arg is DBNull, Nothing or String.Empty, the function defaults to returning an empty string, but you can override this behavior by passing a String of your choice as the second parameter:

    '****************************************************************
    ' NullSafeString
    '****************************************************************
    Public Shared Function NullSafeString(ByVal arg As Object, _
    Optional ByVal returnIfEmpty As String = "") As String
    
      Dim returnValue As String
    
      If (arg Is DBNull.Value) OrElse (arg Is Nothing) _
                       OrElse (arg Is String.Empty) Then
        returnValue = returnIfEmpty
      Else
        Try
          returnValue = CStr(arg).Trim
        Catch
          returnValue = returnIfEmpty
        End Try
    
      End If
    
      Return returnValue
    
    End Function

Using the above function which resides in my Utility class, the code to pull FirstName from the DataSet becomes:

Dim firstName as string = _
    Utility.NullSafeString(ds.Tables(0).Rows("FirstName"), "Not Available")

This function guarantees that the value of firstName is safe to work with. In other words, method calls like firstName.Length, firstName.Replace will not throw exceptions.

Integers, Doubles, and Booleans

To ensure a value is strongly-typed upon its return from the NullSafe function, I create a new method for each data type. On most projects, I have four NullSafe methods, but on a few, I've had to extend to six to encompass Longs and Shorts. Below are my NullSafeInteger, NullSafeDouble, and NullSafeBoolean methods. You'll notice the default return value for the numeric functions is WILDCARD_ID, a constant I create with a value of -1. In the calling code, I can then check for this constant value to determine if the value is "valid."

  '****************************************************************
  ' NullSafeInteger
  '****************************************************************
  Public Shared Function NullSafeInteger(ByVal arg As Object, _ 
    Optional ByVal returnIfEmpty As Integer = Constants.WILDCARD_ID) As Integer

    Dim returnValue As Integer

    If (arg Is DBNull.Value) OrElse (arg Is Nothing) _
                     OrElse (arg Is String.Empty) Then
      returnValue = returnIfEmpty
    Else
      Try
        returnValue = CInt(arg)
      Catch
        returnValue = returnIfEmpty
      End Try
    End If

    Return returnValue

  End Function

  '****************************************************************
  '   NullSafeDouble
  '****************************************************************
  Public Shared Function NullSafeDouble(ByVal arg As Object, _ 
    Optional ByVal returnIfEmpty As Integer = Constants.WILDCARD_ID) As Double

    Dim returnValue As Double

    If (arg Is DBNull.Value) OrElse (arg Is Nothing) _
                     OrElse (arg Is String.Empty) Then
      returnValue = returnIfEmpty
    Else
      Try
        returnValue = CDbl(arg)
      Catch
        returnValue = returnIfEmpty
      End Try
    End If

    Return returnValue

  End Function
  
  '****************************************************************
  ' NullSafeBoolean
  '****************************************************************
  Public Shared Function NullSafeBoolean(ByVal arg As Object) As Boolean

    Dim returnValue As Boolean

    If (arg Is DBNull.Value) OrElse (arg Is Nothing) _
                     OrElse (arg Is String.Empty) Then
      returnValue = False
    Else
      Try
        returnValue = CBool(arg)
      Catch
        returnValue = False
      End Try
    End If

    Return returnValue

  End Function

Conclusion

There is nothing magical about these functions; they simply encapsulate repetitive and cumbersome code into easy to use functions. Best of luck putting them to use!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

rwalling



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralThis can be much simpler PinmemberSébastien Lorion19:27 7 Nov '04  
GeneralAlso ... PinmemberSébastien Lorion19:40 7 Nov '04  
GeneralRe: This can be much simpler Pinmemberrwalling19:13 9 Nov '04  
GeneralRe: This can be much simpler PinmemberSébastien Lorion22:25 9 Nov '04  
GeneralRe: This can be much simpler Pinmemberrwalling18:01 11 Nov '04  
GeneralRe: This can be much simpler PinsussAnonymous14:31 2 Feb '05  
GeneralRe: This can be much simpler PinsussAnonymous18:08 2 Feb '05  
GeneralRe: This can be much simpler Pinmemberrobhughadams5:24 2 Nov '07  
GeneralRe: This can be much simpler PinmemberMatthew D7:06 3 Feb '05  
GeneralRe: This can be much simpler PinmemberSébastien Lorion7:28 3 Feb '05  
GeneralRe: This can be much simpler PinmemberMatthew D7:54 3 Feb '05  
GeneralRe: This can be much simpler PinmemberSébastien Lorion8:10 3 Feb '05  
GeneralRe: This can be much simpler PinmemberMatthew D8:20 3 Feb '05  
If you need alternate functionality, Inherit or wrap the Typed Dataset in another class. That way you separate the changed code from the generated code.
 
Antoher approach is to use something like CodeSmith (www.ericjsmith.com/codesmith) to create typed datasets of your design.
 
Remeber, every line of code you don't have to write, is one you didn't make a mistake on. Even better, you still get paid for it. Wink | ;-)
 
I typically will change the XSD file many times during development (I use Test Driven methodologies) and just keep using the regenerated Dataset.

create/modify a test
 
Add new tables, new fields, change types, modify SQL,
generate the Dataset
fix the code to use the new/renamed/deleted properties and methods
run the test
 
Repeat as required
 
You get to work on the business value, not the infrastructure.
 
Matthew
GeneralRe: This can be much simpler PinmemberSébastien Lorion8:51 3 Feb '05  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120528.1 | Last Updated 7 Nov 2004
Article Copyright 2004 by rwalling
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid