Type Conversions in .NET

Updated: followed suggestion to consider the case where the destination type is an interface. Thanks, Asp.net dev!

Sometimes we have an instance of some class that is not exactly the one we want. This can either be because it is not typed – is of type Object – or for some other reason. When that happens, we need to convert it.

There are several ways that the .NET allows for doing more or less automated conversions between types. I usually use the following function, which does this:

  1. Matching type: if the destination type can be assigned from the source value type, either it is a subclass of the destination type or it implements it (destination type is an interface);
  2. Destination type String: this is pretty obvious, just call ToString() on the source value;
  3. IConvertible implementations: if both types implement IConvertible – normally only base types do –, then we can call Convert.ChangeType method;
  4. Destination type TypeConverter: if the destination type provides a type converter, normally by a TypeConverterAttribute, and this type converter allows converting from the source, then use it for the conversion;
  5. Source type TypeConverter: if the source value provides a type converter and it can convert to the destination type, then use it;
  6. Implicit and explicit conversion operators: if the source value has implicit or explicit conversion operators for the destination type, use them.

The code looks like this:

   1: public static Object Convert(Object value, Type destinationType)
   2: {
   3:     //if value is null, nothing we can do
   4:     if (value == null)
   5:     {
   6:         return (null);
   7:     }
   8:  
   9:     //if no destination type is supplied, just return the source object
  10:     if (destinationType == null)
  11:     {
  12:         return (value);
  13:     }
  14:  
  15:     //if types are compatible, return the source object
  16:     if ((destinationType.IsInstanceOfType(value) == true) || (value.GetType().GetInterfaces().Contains(destinationType)))
  17:     {
  18:         return (value);
  19:     }
  20:  
  21:     //if the destination type is string, just call ToString()
  22:     if (destinationType == typeof(String))
  23:     {
  24:         return (value.ToString());
  25:     }
  26:  
  27:     //if both types are IConvertible, call ChangeType()
  28:     if ((typeof(IConvertible).IsAssignableFrom(destinationType) == true) && (typeof(IConvertible).IsAssignableFrom(value.GetType()) == true))
  29:     {
  30:         return (System.Convert.ChangeType(value, destinationType));
  31:     }
  32:  
  33:     //if the destination type has a type converter that can handle the source object, use it
  34:     var converter = TypeDescriptor.GetConverter(destinationType);
  35:  
  36:     if ((converter != null) && (converter.CanConvertFrom(value.GetType()) == true))
  37:     {
  38:         return (converter.ConvertFrom(value));
  39:     }
  40:  
  41:     converter = TypeDescriptor.GetConverter(value.GetType());
  42:  
  43:     //if the source value has a type converter that can handle the destination type, use it
  44:     if ((converter != null) && (converter.CanConvertTo(destinationType) == true))
  45:     {
  46:         return (converter.ConvertTo(value, destinationType));
  47:     }
  48:  
  49:     //check if the type has an explicit conversion operator and use it
  50:     var conversionOperator = value.GetType().GetMethod("op_Explicit", BindingFlags.Static | BindingFlags.Public);
  51:  
  52:     if ((conversionOperator.ReturnType == destinationType) && (conversionOperator.GetParameters().Length == 1) && (conversionOperator.GetParameters()[0].ParameterType.IsAssignableFrom(value.GetType()) == true))
  53:     {
  54:         return (conversionOperator.Invoke(null, new Object[] { value }));
  55:     }
  56:  
  57:     //check if the type has an implicit conversion operator and use it
  58:     conversionOperator = value.GetType().GetMethod("op_Implicit", BindingFlags.Static | BindingFlags.Public);
  59:  
  60:     if ((conversionOperator.ReturnType == destinationType) && (conversionOperator.GetParameters().Length == 1) && (conversionOperator.GetParameters()[0].ParameterType.IsAssignableFrom(value.GetType()) == true))
  61:     {
  62:         return (conversionOperator.Invoke(null, new Object[] { value }));
  63:     }
  64:  
  65:     //maybe throw an exception instead?
  66:     return (null);
  67: }

So, am I missing anything? Do let me know! Winking smile

                             

2 Comments

  • What about conversion to an Interface or a class within the sources' class hierarchy? Because of the statement (destinationType.IsInstanceOfType(value) == true) this is not possible with your solution as the source type is always returned.

  • Hi!
    Yes, you are right! We need something like:

    if (value.GetType().GetInterfaces().Contains(destinationType) == true)

    right?
    Will update the post accordingly!
    Thanks!

Add a Comment

As it will appear on the website

Not displayed

Your website