Check if types are castable / subclasses

Viewed 17472

I have they type of two members as strings - and not as a Type instance. How can I check if the two types are castable? Let's say string one is "System.Windows.Forms.Label" and the other one is "System.Windows.Forms.Control". How can I check if the first one is a subclass (or implicit castable) of the second one? Is this possible by using reflection?

Thanks for you support!

6 Answers

It might seem like you should use Type.IsAssignableFrom but note carefully the documentation:

public virtual bool IsAssignableFrom(Type c)

true if c and the current [instance of] Type represent the same type, or if the current [instance of] Type is in the inheritance hierarchy of c, or if the current [instance of] Type is an interface that c implements, or if c is a generic type parameter and the current [instance of] Type represents one of the constraints of c. false if none of these conditions are true, or if c is a null reference (Nothing in Visual Basic).

In particular:

class Base { }
clase NotABase { public static implicit operator Base(NotABase o) { // } }

Console.WriteLine(typeof(Base).IsAssignableFrom(typeof(NotABase)));

will print False on the console even though NotABases are implicitly castable to Bases. So, to handle casting, we could use reflection like so:

static class TypeExtensions {
    public static bool IsCastableTo(this Type from, Type to) {
        if (to.IsAssignableFrom(from)) {
            return true;
        }
        return from.GetMethods(BindingFlags.Public | BindingFlags.Static)
                          .Any(
                              m => m.ReturnType == to && 
                                   (m.Name == "op_Implicit" || 
                                    m.Name == "op_Explicit")
                          );
    }
}

Usage:

Console.WriteLine(typeof(string).IsCastableTo(typeof(int))); // false
Console.WriteLine(typeof(NotABase).IsCastableTo(typeof(Base))); // true

And for your case

// from is string representing type name, e.g. "System.Windows.Forms.Label"
// to is string representing type name, e.g. "System.Windows.Forms.Control"
Type fromType = Type.GetType(from);
Type toType = Type.GetType(to);
bool castable = from.IsCastableTo(to);

If you can convert these strings to Type objects then your best bet is Type.IsAssignableFrom.

Beware though, this only tells you if two Type instances are compatible at a CLR level. This will not take into account such things as user defined conversions or other C# semantics.

How about:

public bool IsCastable(String type0, String type1)
{
  return Type.GetType(type1).IsAssignableFrom(Type.GetType(type0));
}

Simplest way is value.GetType().IsSubclassOf(typeof(Control)) Basically, Type.IsSubclassOf method do what you need

Related