#582 – Use the as Operator to Unbox to a Nullable Type

You can box regular value types or their equivalent nullable types (e.g. int and int?) and the boxed values will either be null or be of the underlying value type.

You can unbox these values to a nullable type, or use the as operator to do the unboxing.  The example below shows the result of unboxing several different values to a nullable int (int?) using the as operator.

int? i1 = null;   // Nullable<int> w/no value
int? i2 = 42;     // Nullable<int> with a value
int i3 = 12;      // Plain old int

// Boxing nullable types
object o1 = i1;
object o2 = i2;
object o3 = i3;
object o4 = new Dog("I'm not an int", 12);

// Unboxing to nullable types
int? ia1 = o1 as int?;    // null
int? ia2 = o2 as int?;    // 42
int? ia3 = o3 as int?;    // 12
int? ia4 = o4 as int?;    // null

bool bHasVal = ia1.HasValue;  // false
bHasVal = ia2.HasValue;       // true
bHasVal = ia3.HasValue;       // true
bHasVal = ia4.HasValue;       // false

#217 – T? Is Equivalent to Nullable<T>

You can always use the form T?, rather than Nullable<T>, to declare a variable whose type is a nullable value type.  The type T can be any built-in or custom value type.

This means that you can use this syntax for your own custom enum or struct types.

For example, if you have the following custom types:

        public enum Mood
        {
            Crabby,
            Happy,
            Petulant,
            Elated
        }

        public struct Point3D
        {
            public float X, Y, Z;
            public string Name;
            public Point3D(float x, float y, float z, string name)
            {
                X = x;
                Y = y;
                Z = z;
                Name = name;
            }
        }

You can use the T? format as follows:

            Mood? myMood = null;
            Mood mood2 = myMood ?? Mood.Elated;

            Point3D? somePoint = null;
            Point3D defaultPoint = new Point3D(0.0f, 0.0f, 0.0f, "Origin");
            Point3D aPoint = somePoint ?? defaultPoint;

#216 – Null-Coalescing (??) Operator Is Equivalent to GetValueOrDefault Method

The Nullable<T> type has a GetValueOrDefault(T) method that behaves in a way identical to the ?? operator.  It returns the value of the object, if non-null, or the value of the parameter passed in if the object is null.

            Nullable<Mood> myMood = null;

            Mood mood2 = myMood ?? Mood.Happy;   // result = Happy, since myMood is null
            Mood mood3 = myMood.GetValueOrDefault(Mood.Happy);   // same as above

There is also an overload of the GetValueOrDefault method that doesn’t take a parameter but just returns the default value for the type T, if the object in question is null.  For example, an enum type has a default value of 0, so the enumerated constant equivalent to 0 is returned.

        public enum Mood
        {
            Crabby,   // 0-valued
            Happy,
            Petulant,
            Elated
        }

            Nullable<Mood> myMood = null;

            Mood mood2 = myMood.GetValueOrDefault();   // Gets value Mood.Crabby

#215 – Using the Null-Coalescing (??) Operator with Custom Nullable Types

In addition to the built-in nullable types, you can also use the null-coalescing operator on custom nullable types using Nullable<T>.

Here’s an example:

            Nullable<Mood> myMood1 = null;
            Nullable<Mood> myMood2 = Mood.Petulant;

            Mood mood3 = myMood1 ?? Mood.Happy;   // result = Happy
            Mood mood4 = myMood2 ?? Mood.Happy;   // result = Petulant

#214 – Using the Null-Coalescing (??) Operator with Reference Types

The ?? operator is often used with nullable value types, assigning a value to an equivalent non-nullable type (e.g. int? to int).  But it can also be used with reference types.

The behavior with reference types is the same as with value types–the value of the expression is equal to the first operand, if non-null, or the second operand if the first operand is null.

Here’s an example:

            Person favArtist = new Person("Connee", "Boswell");
            Person oldBlueEyes = new Person("Frank", "Sinatra");

            Person buyCDOf = favArtist ?? oldBlueEyes;  // Frank is our fallback

In this example, buyCDOf will be assigned the Connee Boswell Person object.  But if the favArtist variable had been null, we would have defaulted to assigning buyCDOf to Frank Sinatra.

#211 – Using the Null-Coalescing (??) Operator

In C#, the ?? operator, know as the null-coalescing operator, is often used with nullable types.

The ?? operator is used in an expression of the form:

            operand ?? nullval

This expression evaluates to:

  • operand, if operand is non-null
  • nullval, if operand is null

The operand is a variable and the nullval is a variable or constant of the same type as the variable.

The ?? operator is generally used where you have a nullable type and you want to assign its value to a non-nullable type.  Since the nullable type can have the value of null, you need to specify what non-null value to assign in that case.

Here’s an example:

            uint? age = null;   // Nullable age -- might not have a value

            // Later: assign to a non-nullable uint.
            //   Store the age (if non-null)
            //   Store 0  (if null)
            uint ageStore = age ?? 0;

#210 – Checking to See Whether a Nullable Object Has a Value

Both the built-in nullable types (e.g. int?) and any Nullable<T> types that you use have a HasValue property that lets you determine whether a particular nullable object has a value or not.

  • HasValue is true if the object has a value of the corresponding type
  • HasValue is false if the object has a null value

For example, if you are using a nullable int:

            int? herAge = null;

And you later want to see if this variable has a value (of type int), you can do this:

            if (herAge.HasValue)
                Console.WriteLine("She is {0} yrs old", herAge);

HasValue is useful in cases when you want to perform an operation on an object, where the operation is only valid if the object is non-null.

#209 – Why You’d Want to Store a Null Value in a Variable

The Nullable<T> type lets us make any value type nullable.  But why is this useful?  When might we want to store a null value in a type, in addition to the normal range of values?

It’s often useful to represent the fact that a variable doesn’t have a value.

For example, assume that we have a class that stores some information about a book that we have read.  We might have a DateStarted and a DateFinished field:

            DateTime DateStarted;
            DateTime DateFinished;

If we want to be able to store information representing a book that has been started, but not yet finished, we’d want to store a value for DateStarted, but no value for DateFinished.  With a normal DateTime value, we couldn’t do this.  Instead, we make both fields nullable, allowing us to store a null value for either.

            DateTime? DateStarted;
            DateTime? DateFinished;

#208 – You Can Make Any Value Type Nullable

The ? character that indicates a nullable type is really a shortcut to the System.Nullable<T> structure, where T is the type being made nullable.  In other words, using int? is equivalent to using System.Nullable<System.Int32>.

You can make any value type nullable using the Nullable<T> syntax.  You’d typically do this for your own custom struct or enum types.

For example, assume that you have the following two custom types.

        // How I'm feeling
        public enum Mood
        {
            Crabby,
            Happy,
            Petulant,
            Elated
        }

        // A 3D point with a name
        public struct Point3D
        {
            public float X, Y, Z;
            public string Name;
        }

You can use these types as nullable types using Nullable<T>.

            Nullable<Mood> me = Mood.Crabby;
            me = null;

            Nullable<Point3D> nonPoint = null;

Follow

Get every new post delivered to your Inbox.

Join 43 other followers