Problem
Often in code, we need to cast an object of one type to another at run-time, for example:
Customer customer = myObject as Customer;
int number = (int) myObject;
However, if we forget to add the neccessary code to check that the object is of the expected type to be converted, we end up with the following error message(s) that do not help to determine WHY the cast failed:
Specified cast is not valid.
or
Object reference not set to an instance of an object.
Solution
Use an extension method on the
Object
class to perform a cast on any object in code and at run-time be assured that casting the wrong type will give us a useful error message to help solve the problem. For example:
Customer customer = myObject.CastTo<customer>();
An invalid cast results in an
InvalidCastException
error message that tells us why a cast failed:
"Expected object 'Joe Bloggs' to be of type MyCompany.Customer. Actual type is MyCompany.Manager."
The code for the
Cast
extension method is as follows:
/// <summary>
/// Extension methods for the <c>object</c> class.
/// </summary>
/// <remarks>
/// Works only in .NET 3.5+
/// </remarks>
public static class ObjectExtensions
{
/// <summary>
/// Casts the supplied object to the value or reference type <c>T</c>, throwing an <c>InvalidCastException</c> with a useful message if the object is not of type <c>T</c>.
/// </summary>
/// <remarks>
/// 'CastTo' name is used instead of simply 'Cast' to avoid clashes with LINQ extension methods with the same name.
/// </remarks>
/// <param name="input">Object to be cast.</param>
/// <exception cref="InvalidCastException">Thrown if <paramref name="input"/> is not of type <c>T</c>.</exception>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="input"/> is null.</exception>
/// <returns>Object cast to of type <c>T</c>.</returns>
public static T CastTo<T>(this object input)
{
T output;
if (input != null)
{
if (input is T)
{
output = (T) input;
}
else
{
string message = String.Format("Expected object '{0}' to be of type {1}. Actual type is {2}", input.ToString(), typeof(T).Name, input.GetType().Name);
throw new InvalidCastException(message);
}
}
else
{
throw new ArgumentNullException("input");
}
return output;
}
}