IsAssignableFrom, IsInstanceOfType and the is keyword, what is the difference?

前端 未结 4 678
醉梦人生
醉梦人生 2020-12-02 22:41

I have an extension method to safe casting objects, that looks like this:

public static T SafeCastAs(this object obj) {
    if (obj == null)
                


        
相关标签:
4条回答
  • 2020-12-02 22:57

    I guess you're effectively implementing a version of the as operator that works with value types as well as reference types.

    I'd go for:

    public static T SafeCastAs<T>(this object obj)
    {
        return (obj is T) ? (T) obj : default(T);
    }
    

    IsAssignableFrom works with types, and is works with instances. They will give you the same results in your case, so you should use the simplest version IMHO.

    As for IsInstanceOfType:That is implemented in terms of IsAssignableFrom, so there will be no difference.

    You can prove that by using Reflector to look at the definition of IsInstanceOfType():

    public virtual bool IsInstanceOfType(object o)
    {
        if (o == null)
        {
            return false;
        }
        return this.IsAssignableFrom(o.GetType());
    }
    
    0 讨论(0)
  • 2020-12-02 22:59

    You use whatever you have the information for.

    If you have an instance and a static type you want to check against, use is.

    If you don't have the static type, you just have a Type object, but you have an instance you want to check, use IsInstanceOfType.

    If you don't have an instance and you just want to check the compatibility between a theoretical instance of a Type and another Type, use IsAssignableFrom.

    But really is seems like you are just re-implementing the as operator (except that yours would also work for non-nullable value types, which is usually not a big limitation).

    0 讨论(0)
  • 2020-12-02 23:02

    These functions and operators have different meaning. If you have objects you can always get types. so you do not work on what you have, but you do what needs to be done.

    When you are working with a class hierarchy differences are very clear.

    Look at following example

          class ABase
            {
    
            }
    
            class BSubclass : ABase
            {
    
            }
        ABase aBaseObj = new ABase();
                    BSubclass bSubclassObj = new BSubclass();
    
                    ABase subObjInBaseRef = new BSubclass();
    

    Different operations yield different results.

    typeof(ABase).IsInstanceOfType(aBaseObj) = True
    
    typeof(ABase).IsInstanceOfType(bSubclassObj) = True
    
    typeof(ABase).IsInstanceOfType(bSubclassObj) = True
    
    typeof(BSubclass).IsInstanceOfType(aBaseObj) = False
    
    bSubclassObj is ABase = True
    
    aBaseObj is BSubclass = False
    
    subObjInBaseRef is BSubclass = True
    
    subObjInBaseRef is BSubclass = True
    
    typeof(ABase).IsAssignableFrom(typeof(BSubclass))  = True
    
    typeof(BSubclass).IsAssignableFrom(typeof(ABase))= False
    

    In case on no hierarchy, may be everything was same. But if you work with hierarchy, IsAssignableFrom , is , and IsInstanceOfType yield different results.

    There are more possible combinations that could be tried. For example, you can introduce a class C which is not related in anyway with existing classes in this example.

    0 讨论(0)
  • 2020-12-02 23:15

    I guess you should just go with "as" instead of your custom "SafeCastAs". But this will work only for classes (not structs), so if you want to use this method for structs as well I can get it.

    Operator "is" basically gives you the same as Type.IsAssignableFrom, so you can keep only "is", it checks if you can safely cast obj to T, without exceptions. So it will cover both previous checks in your method. But you should be aware about that it does not check if you can assign obj to T, because of user defined conversions: explicit and implicit keywords.

    0 讨论(0)
提交回复
热议问题