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

#580 – as Operator Can Generate Compile-Time Errors

The as operator can perform reference conversions between types in a type hierarchy, returning null if the conversion is not possible.  But there are some cases when the compiler knows that no conversion is possible between the specified types, so it will generate an error at compile time.

Dog d = new Dog("Lassie", 12);

// Can't convert a Dog to a Cow--compile-time error
Cow c = d as Cow;

#579 – Typical Pattern for Using as Operator

When you use the as operator to attempt to convert an expression to a particular type, you typically follow the pattern shown below.

In most cases, you have a variable of a base class that stores some object and you use the as operator to determine if it stores an object of a particular derived type.  In the example below, Terrier is a class that inherits from Dog.

            // Dog variable referring to object of type Terrier
            Dog d = new Terrier("Jack", 17, "Crabby");

            // Elsewhere in our code, we have variable
            // of type Dog and want to see if it refers to a
            // Terrier.
            Terrier t = d as Terrier;
            if (t != null)
                t.TerrierMethod();

You can do the same thing with the is operator, though it is a little less efficient, because it actually does the type conversion twice.

            // A bit less efficient
            if (d is Terrier)
                ((Terrier)d).TerrierMethod();

#578 – Using the as Operator to Do Type Conversions

The as operator attempts to convert an expression to a specified type, returning the value of null if the conversion fails.  It behaves similarly to doing the conversion using a cast, but does not throw an exception if the cast fails.

// (Terrier is a sub-class of Dog)

Dog d = new Dog("Fido", 5);
Terrier t = new Terrier("Jack", 17, "Crabby");
Dog d2 = t;

Dog dTest = d as Dog;   // ok
dTest = d as Terrier;   // null

dTest = t as Dog;       // ok
Terrier tTest = t as Terrier;   // ok

dTest = d2 as Dog;      // ok
tTest = d2 as Terrier;  // ok

Object oTest = d as object;    // ok

#447 – Use as Operator to Get At an Object’s Interfaces

If a class implements an interface, you can assign a variable whose type is that class directly to a variable of the interface’s type.

            Cow bossie = new Cow("Bossie", 12);

            IMoo viaMoo = bossie;
            viaMoo.Moo();

However, there might be times when you have a variable of a more general type and the variable may or may not implement a particular interface. In these cases, you could use a dynamic cast to cast the object variable to the interface type.

            object objSomething = bossie;

            // Can't assign directly; need cast
            IMoo viaMoo = (IMoo)objSomething;
            viaMoo.Moo();

The only problem is that this cast will fail, throwing an InvalidCastException, if the object does not implement IMoo.  Instead, you can use the as operator, which essentially does the cast, but just returns null if the cast fails.

            IMoo viaMoo = objSomething as IMoo;
            if (viaMoo != null)
                viaMoo.Moo();