Direct casting vs 'as' operator?

后端 未结 16 1841
独厮守ぢ
独厮守ぢ 2020-11-22 01:43

Consider the following code:

void Handler(object o, EventArgs e)
{
   // I swear o is a string
   string s = (string)o; // 1
   //-OR-
   string s = o as str         


        
16条回答
  •  -上瘾入骨i
    2020-11-22 02:20

    It seems the two of them are conceptually different.

    Direct Casting

    Types don't have to be strictly related. It comes in all types of flavors.

    • Custom implicit/explicit casting: Usually a new object is created.
    • Value Type Implicit: Copy without losing information.
    • Value Type Explicit: Copy and information might be lost.
    • IS-A relationship: Change reference type, otherwise throws exception.
    • Same type: 'Casting is redundant'.

    It feels like the object is going to be converted into something else.

    AS operator

    Types have a direct relationship. As in:

    • Reference Types: IS-A relationship Objects are always the same, just the reference changes.
    • Value Types: Copy boxing and nullable types.

    It feels like the you are going to handle the object in a different way.

    Samples and IL

        class TypeA
        {
            public int value;
        }
    
        class TypeB
        {
            public int number;
    
            public static explicit operator TypeB(TypeA v)
            {
                return new TypeB() { number = v.value };
            }
        }
    
        class TypeC : TypeB { }
        interface IFoo { }
        class TypeD : TypeA, IFoo { }
    
        void Run()
        {
            TypeA customTypeA = new TypeD() { value = 10 };
            long longValue = long.MaxValue;
            int intValue = int.MaxValue;
    
            // Casting 
            TypeB typeB = (TypeB)customTypeA; // custom explicit casting -- IL:  call class ConsoleApp1.Program/TypeB ConsoleApp1.Program/TypeB::op_Explicit(class ConsoleApp1.Program/TypeA)
            IFoo foo = (IFoo)customTypeA; // is-a reference -- IL: castclass  ConsoleApp1.Program/IFoo
    
            int loseValue = (int)longValue; // explicit -- IL: conv.i4
            long dontLose = intValue; // implict -- IL: conv.i8
    
            // AS 
            int? wraps = intValue as int?; // nullable wrapper -- IL:  call instance void valuetype [System.Runtime]System.Nullable`1::.ctor(!0)
            object o1 = intValue as object; // box -- IL: box [System.Runtime]System.Int32
            TypeD d1 = customTypeA as TypeD; // reference conversion -- IL: isinst ConsoleApp1.Program/TypeD
            IFoo f1 = customTypeA as IFoo; // reference conversion -- IL: isinst ConsoleApp1.Program/IFoo
    
            //TypeC d = customTypeA as TypeC; // wouldn't compile
        }
    

提交回复
热议问题