Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell if Type A is implicitly convertible to Type B

Given Type a and Type b, how can I, at runtime, determine whether there's an implicit conversion from a to b?

If that doesn't make sense, consider the following method:

public PropertyInfo GetCompatibleProperty<T>(object instance, string propertyName) {    var property = instance.GetType().GetProperty(propertyName);     bool isCompatibleProperty = !property.PropertyType.IsAssignableFrom(typeof(T));    if (!isCompatibleProperty) throw new Exception("OH NOES!!!");     return property;    } 

And here's the calling code that I want to work:

// Since string.Length is an int property, and ints are convertible // to double, this should work, but it doesn't. :-( var property = GetCompatibleProperty<double>("someStringHere", "Length"); 
like image 810
Judah Gabriel Himango Avatar asked Feb 08 '10 19:02

Judah Gabriel Himango


People also ask

What is implicit type conversion?

Implicit type conversion in C language is the conversion of one data type into another datatype by the compiler during the execution of the program. It is also called automatic type conversion.

When can an implicit conversion occur between classes?

Implicit Type Conversion is also known as 'automatic type conversion'. It is done by the compiler on its own, without any external trigger from the user. It generally takes place when in an expression more than one data type is present.

Which of the following defines implicit casting?

In implicit typecasting, the conversion involves a smaller data type to the larger type size. For example, the byte datatype implicitly typecast into short, char, int, long, float, and double. The process of converting the lower data type to that of a higher data type is referred to as Widening.

What is implicit casting C++?

Implicit type conversion also known as automatic type conversion is carried out by the compiler without the need for a user-initiated action. It takes place when an expression of more than one data type is present which in such an instance type conversion takes place to avoid data loss.


2 Answers

Note that IsAssignableFrom does NOT solve your problem. You have to use Reflection like so. Note the explicit need to handle the primitive types; these lists are per §6.1.2 (Implicit numeric conversions) of the specification.

static class TypeExtensions {      static Dictionary<Type, List<Type>> dict = new Dictionary<Type, List<Type>>() {         { typeof(decimal), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(char) } },         { typeof(double), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(char), typeof(float) } },         { typeof(float), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(long), typeof(ulong), typeof(char), typeof(float) } },         { typeof(ulong), new List<Type> { typeof(byte), typeof(ushort), typeof(uint), typeof(char) } },         { typeof(long), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), typeof(char) } },         { typeof(uint), new List<Type> { typeof(byte), typeof(ushort), typeof(char) } },         { typeof(int), new List<Type> { typeof(sbyte), typeof(byte), typeof(short), typeof(ushort), typeof(char) } },         { typeof(ushort), new List<Type> { typeof(byte), typeof(char) } },         { typeof(short), new List<Type> { typeof(byte) } }     };     public static bool IsCastableTo(this Type from, Type to) {          if (to.IsAssignableFrom(from)) {              return true;          }         if (dict.ContainsKey(to) && dict[to].Contains(from)) {             return true;         }         bool castable = from.GetMethods(BindingFlags.Public | BindingFlags.Static)                          .Any(                              m => m.ReturnType == to &&                               (m.Name == "op_Implicit" ||                               m.Name == "op_Explicit")                         );          return castable;      }  }  

Usage:

bool b = typeof(A).IsCastableTo(typeof(B)); 
like image 154
jason Avatar answered Sep 19 '22 16:09

jason


Implicit conversions you'll need to consider:

  • Identity
  • sbyte to short, int, long, float, double, or decimal
  • byte to short, ushort, int, uint, long, ulong, float, double, or decimal
  • short to int, long, float, double, or decimal
  • ushort to int, uint, long, ulong, float, double, or decimal
  • int to long, float, double, or decimal
  • uint to long, ulong, float, double, or decimal
  • long to float, double, or decimal
  • ulong to float, double, or decimal
  • char to ushort, int, uint, long, ulong, float, double, or decimal
  • float to double
  • Nullable type conversion
  • Reference type to object
  • Derived class to base class
  • Class to implemented interface
  • Interface to base interface
  • Array to array when arrays have the same number of dimensions, there is an implicit conversion from the source element type to the destination element type and the source element type and the destination element type are reference types
  • Array type to System.Array
  • Array type to IList<> and its base interfaces
  • Delegate type to System.Delegate
  • Boxing conversion
  • Enum type to System.Enum
  • User defined conversion (op_implicit)

I assume you're looking for the latter. You'll need to write something resembling a compiler to cover all of them. Notable is that System.Linq.Expressions.Expression didn't attempt this feat.

like image 45
Hans Passant Avatar answered Sep 18 '22 16:09

Hans Passant