25 August 2010

Efficient Use of Nullable Types

I saw a brief post about nullable types, today, and realized (not by fault of the post itself, rather through my own experiences) that a surprising number of .NET developers either don't know they exist, don't use them correctly, or don't use them efficiently.  Furthermore, nullable types were a topic of the C# class I just finished conducting.

What is a nullable type?
Nullable types help us circumvent the problem on not being able to set a value type to a null value, after it has been initialized.  To understand why value types can not be assigned a null value, I recommend reading about .NET Stack and Heap memory.

Value types are values that reside in private stack, including:
  • (all integers)
  • (all floating-point numbers)
  • char
  • bool
Stack memory only contains these value types.  Pointers to heap objects are simply 32- or 64- bit integers (depending on if compiled to x86 or x64) that contain the heap memory address of the object instance.  Because a value type is, by definition, simply a value occupying a memory address, it can not contain nothing (null) -- it must contain some value, even if it is zero. Zero is a value, and is not mull -- pointers pointing to null are actually pointing to address 0x0, which is reserved for "null".

Nullable types are types that are able to contain a null value.  All value types have a nullable version.

How nullable types work
A nullable type really isn't a type in itself.  These are simply implementations of the Nullable generic struct.  All .NET types implement this generic struct through the " ? " operator.  Although structs reside in the private stack and are not subject to boxing, they aren't as efficient as the normal value type.  Therefore, only use a nullable type when needed.

Syntax & Evaluation
Because a nullable type is a struct, we can not (should not) evaluate their value as one would a value type. We must call the Value property, to retrieve it. (Fortunately, .NET accommodates programmers not aware of this need, by providing a mechanism allowing normal value type syntax, given the value is not null.)_

To declare a type as nullable, simply post-fix the type name with the " ? " character.  For example:
// Declare a nullable type
int? nullableType = 356;
nullableType = null;
If we replace int? with just regular int, the above code will not compile.  As mentioned earlier, the nullable type value must be retrieved by way of the Value property:
// Declare a nullable type
int? nullableType = 356;
nullableType = null;

// Declare a value type -- this can not be set to null!
int valueType;

// This line will cause a runtime error, because the returned
// value is null. Value types can not be set to null!
value type = nullableTypeInt; 

// We may determine if the nullable type contains  a null
// value, and then make an assignment.  Also, we will
// retrieve the value by calling the Value property.
if (!nullableType.HasValue)
    valueType = nullableType.Value;

// We can set a default value, when the nullable
// type has no (null) value.
const int defaultValue = -1;

if (!nullableTypeInt.HasValue)
    valueType = nullableType.Value;
    valueType = defaultValue;

// Nullable<t> provides the Null Coalescing Operator (??),
// to reduce the amount of code needed to achieve
// the same results as above.  This works similar
// to the ternary (?:) operator.
valueType = nullableType ?? defaultValue;

Efficient Use of Nullable Types
There are only a few basic rules to efficient use of nullable types, all of which you probably already know or have guessed:
  1. Use nullable types only when needed
  2. Check for null by calling the HasValue property, before attempting to use the value
  3. Retrieve the value by calling the Value property
  4. Use the ?? operator, to save space and time

No comments:

Post a Comment

Please provide details, when posting technical comments. If you find an error in sample code or have found bad information/misinformation in a post, please e-mail me details, so I can make corrections as quickly as possible.