Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test if Convert.ChangeType will work between two types

Tags:

c#

reflection

This is a follow-up to this question about converting values with reflection. Converting an object of a certain type to another type can be done like this:

object convertedValue = Convert.ChangeType(value, targetType); 

Given two Type instances (say FromType and ToType), is there a way to test whether the conversion will succeed?

E.g. can I write an extension method like this:

public static class TypeExtensions {     public static bool CanChangeType(this Type fromType, Type toType)     {         // what to put here?     } } 

EDIT: This is what I have right now. Ugly, but I don't see another way yet...

bool CanChangeType(Type sourceType, Type targetType) {   try   {     var instanceOfSourceType = Activator.CreateInstance(sourceType);     Convert.ChangeType(instanceOfSourceType, targetType);     return true; // OK, it can be converted   }   catch (Exception ex)   {     return false;   } 
like image 555
jeroenh Avatar asked Sep 09 '09 12:09

jeroenh


People also ask

How does convert ChangeType work?

The ChangeType() method returns an object of the specified type and whose value is equivalent to the specified object. Let's say we have a double type. Now, use the ChangeType method to change the type to integer. num = (int)Convert.

How do you solve an object must implement Iconvertible?

you have to implement IConvertable on the object because Covert. ChangeType() expects IConvertable object. So Convert object knows how to convert given object to the type that you need - even it is the same type.


2 Answers

I was just encountering this same issue, and I used Reflector to look at the source for ChangeType. ChangeType throws exceptions in 3 cases:

  1. conversionType is null
  2. value is null
  3. value does not implement IConvertible

After those 3 are checked, it is guaranteed that it can be converted. So you can save a lot of performance and remove the try{}/catch{} block by simply checking those 3 things yourself:

public static bool CanChangeType(object value, Type conversionType) {     if (conversionType == null)     {         return false;     }      if (value == null)     {                       return false;     }      IConvertible convertible = value as IConvertible;      if (convertible == null)     {         return false;     }      return true; } 
like image 101
esac Avatar answered Sep 21 '22 15:09

esac


Checking the method Convert.ChangeType in reflector I found this in the static constructor:

ConvertTypes = new Type[] {          typeof(Empty), typeof(object), typeof(DBNull), typeof(bool), typeof(char), typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal),          typeof(DateTime), typeof(object), typeof(string)      }; 

In the end, this method is just checking either if the source is implementing IConvertible or if the target is one of the ConvertTypes above. So your method should look something like this (very rough):

return (ConvertTypes.Contains(toType) || typeof(IConvertible).IsAssignableFrom(fromType)); 
like image 32
Marc Wittke Avatar answered Sep 21 '22 15:09

Marc Wittke