#1,060 – Explicit Conversions between Nullable Types

An implicit conversion exists between two nullable types if an implicit conversion exists between the corresponding value types.  For example:

int i = 12;
long l = i;  // implicit int to long
int? i2 = 12;
long? l2 = i2;  // implicit int? to long?

Similarly, an explicit conversion exists between two nullable types if an explicit conversion exists between the corresponding value types.

long l = 12;
int i = (int)l;  // explicit long to int
long? l2 = 12;
int? i2 = (int?)l2;  // explicit long? to int?

You can also convert between a nullable and non-nullable type, either implicitly or explicitly.  An explicit conversion is required when converting from a nullable type to a non-nullable type or when an explicit conversion is required by the underlying types.

            int? i3 = (int?)l;   // explicit long to int?
            long l3 = (long)i3;  // explicit int? to long

#1,050 – Implicit Conversions between Nullable Types

You can implicitly convert from a non-nullable value type to a matching nullable type.  For example:

int i = 12;   // regular int, can't be null

int? j = 22;  // Nullable int, can store an int value

You can also implicitly convert between equivalent nullable types.  For example:

            int? nt1 = 5;
            int? nt2 = null;

            int? nt3 = nt1;  // ok
            nt3 = nt2;       // also ok

An implicit conversion is allowed between the nullable types (e.g. from int? to long?) if an implicit conversion exists between the corresponding base types (e.g. from int to long).

#566 – Implicit Conversions to Nullable Types

A nullable type represents a type whose value can be either a particular value type or can be the null value.

int i = 12;   // regular int, can't be null

int? j = 22;  // Nullable int, can store an int value
j = null;     // Can also store null value

You can implicitly convert from the corresponding value type to its matching nullable type.  For example, you can convert from an object of type int to an object of type int?

int i = 12;
int? j = i;   // Implicit conversion from int to int?

float f1 = i;   // Implicit conversion from int to float
float? f2 = i;  // Implicit conversion from int -> float -> float?

You can also implicitly convert from the null value to any nullable type.

int? i = null;

#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;

#207 – Nullable Types

Because value types can’t normally represent null values, C# includes nullable types–types that can represent their normal range of values or represent a null value.

Any value type can be used as a nullable type by adding a trailing ? to the type name.

            int i = 12;   // regular int, can't be null

            int? j = 22;  // Nullable int, can be null
            j = null;     // Can also be null

Here are some other examples of nullable types.  In each case, we can set the variable’s value to null, which means that the variable doesn’t have a value that falls within the range of the corresponding type.

            double? r = null;
            bool? thisIsFalse = null;
            Mood? myMood = null;