The Type
class has a method IsAssignableFrom()
that almost works. Unfortunately it only returns true if the two types are the same or the first is in
There are actually three ways that a type can be “assignable” to another in the sense that you are looking for.
Class hierarchy, interface implementation, covariance and contravariance. This is what .IsAssignableFrom
already checks for. (This also includes permissible boxing operations, e.g. int
to object
or DateTime
to ValueType
.)
User-defined implicit conversions. This is what all the other answers are referring to. You can retrieve these via Reflection, for example the implicit conversion from int
to decimal
is a static method that looks like this:
System.Decimal op_Implicit(Int32)
You only need to check the two relevant types (in this case, Int32
and Decimal
); if the conversion is not in those, then it doesn’t exist.
Built-in implicit conversions which are defined in the C# language specification. Unfortunately Reflection doesn’t show these. You will have to find them in the specification and copy the assignability rules into your code manually. This includes numeric conversions, e.g. int
to long
as well as float
to double
, pointer conversions, nullable conversions (int
to int?
), and lifted conversions.
Furthermore, a user-defined implicit conversion can be chained with a built-in implicit conversion. For example, if a user-defined implicit conversion exists from int
to some type T
, then it also doubles as a conversion from short
to T
. Similarly, T
to short
doubles as T
to int
.