These guidelines were just added as part of an update to the Framework Design Guidelines book (upcomming 2nd edition). Hope you find them useful.

 

Nullable<T> is a simple type added to the .NET Framework 2.0. The type was designed to be able to represent Value Types with “null” values.

Nullable<int> x = null;

Nullable<int> y = 5;

Console.WriteLine(x == null); // prints true

Console.WriteLine(y == null); // prints false

 

Note that C# provides special support for Nullable<T> in the form of language aliases for Nullable types, lifted operators, and the new coalescing operator.

int? x = null; //

long? d = x; // calls cast operator from Int32 to Int64

Console.WriteLine(d??10); // coalescing; prints 10 because d == null

 

þ CONSIDER using Nullable<T> to represent values that might not be present (i.e. optional values). For example, use it when returning a strongly typed record from a database with a property representing an optional table column. 

ý Do NOT use Nullable<T> unless you would use a reference type in a similar manner, taking advantage of the fact that reference type values can be null.

For example, you would not use null to represent optional parameters.

// bad design

public class Foo {

   public Foo(string name, int? id);

}

 

// good design

public class Foo {

   public Foo(string name, int id);

   public Foo(string name);

}

 

ý AVOID using Nullable<bool> to represent a general three-state value.

Nullable<bool> should only be used to represent truly optional Boolean values: true, false, and not available. If you simply want to represent three states (e.g. yes, no, cancel), consider using an enum.

ý AVOID using System.DBNull. Prefer Nullable<T> instead.

Nullable<T> is in general a better representation of optional database values. One thing to consider though it that while Nullable<T> gives you the ability to represent null values, you don’t get database null operational semantics. Specifically, you don’t get null propagation through operators and functions. If you deeply care about the propagation semantics, consider sticking with DBNull.