Programming Tips & Tricks

Home Categories: C# | C++ | General | Other

C# Tips & Tricks: Make Type Conversions With the 'as' Operator

Instead of a normal cast, you can convert types in C# with the 'as' operator.
Thus instead of
B b = (B)a;
you write
B b = a as B;
In almost all cases, you should prefer casting with the 'as' operator, instead of using a normal cast:

1. When a cast fails, a normal cast results in a System.InvalidCastException, which has to be captured in an (expensive) try/catch, or you first have to check for the correct type with the 'is' operator. When you use the 'as' operator, it returns null, so you only have to do a cheap if(result!=null) check afterwards.
2. The 'as' operator doesn't perform user-defined conversions (you can create a user-defined conversion for a type you write by overloading the 'implicit' operator). This might be a negative in some situations for particular types, but usually this is a positive.
The reason is that user-defined conversions are only executed when both concrete types are known at compile-time, which is not the case if you have a base-class or interface reference to one of the types. Thus, depending on if you declare a variable as Base x = new Derived(); or Derived x = new Derived(); a standard cast Y y = (Y)x; can yield a different result. If the compile-time type of x is Derived, a user-defined conversion between Derived and Y will be executed. But if the compile-time type is Base, it will not.
The 'as' operator never executes a user-defined conversion, and is thus more consistent.
3. 'as' is guaranteed to never create temporary objects
4. You don't need to check a reference for null before you cast it with 'as'. MyType x = null as MyType simply results in x == null

The only place where you cannot use 'as' is with value types. These have to be converted with normal casts. Trying to use 'as' on a value type results in a compiler error.
This problem propagates to generic methods, which could receive both value and reference types as input. To use 'as' within a generic method, you must restrict the method to only accept reference type with a 'class' requirement (void Func (T t) where T:class{...})