A question about unboxing

William Liu 306 Reputation points
2021-09-15T07:21:13.73+00:00

Learned the "Boxing and Unboxing (C# Programming Guide)" article from msdn.

These lines are called boxing and unboxing.

int i = 123;  
// The following line boxes i.  
object o = i;  

o = 456;  
i = (int)o;  // unboxing  

My question is, is the following codes also called "unboxing"? If so, does it suffer the same performance penalty like above codes?

int i = 10;  
object o = i;  
if (o is int j) // unboxing?  
{  
    System.Console.WriteLine(j);  
}  

if (o is 10) // one further step, unboxing?  
{  
    System.Console.WriteLine("It`s 10! ");  
}  
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,501 questions
0 comments No comments
{count} votes

Accepted answer
  1. P a u l 10,406 Reputation points
    2021-09-15T09:53:15.63+00:00

    If you're interested in how you'd figure this out you could look at the IL that's generated.

    I use this for testing C# expressions/programs, and you can see the IL that's generated if you click the "IL" button above the results window:
    https://www.linqpad.net

    Once you have the IL all you need to do is cross-reference the instruction codes (for example unbox.any, unbox, stloc, call) to this list:
    https://en.wikipedia.org/wiki/List_of_CIL_instructions

    Your first expression produces IL like the following:

    IL_0000:  nop         
    IL_0001:  ldc.i4.s    0A 
    IL_0003:  stloc.0     // i
    IL_0004:  ldloc.0     // i
    IL_0005:  box         System.Int32
    IL_000A:  stloc.1     // o
    IL_000B:  ldloc.1     // o
    IL_000C:  dup         
    IL_000D:  stloc.s     04 
    IL_000F:  isinst      System.Int32
    IL_0014:  brfalse.s   IL_0021
    IL_0016:  ldloc.s     04 
    IL_0018:  unbox.any   System.Int32
    IL_001D:  stloc.2     // j
    IL_001E:  ldc.i4.1    
    IL_001F:  br.s        IL_0022
    IL_0021:  ldc.i4.0    
    IL_0022:  stloc.3     
    IL_0023:  ldloc.3     
    IL_0024:  brfalse.s   IL_002F
    IL_0026:  nop         
    IL_0027:  ldloc.2     // j
    IL_0028:  call        System.Console.WriteLine
    IL_002D:  nop         
    IL_002E:  nop         
    IL_002F:  ret
    

    You can see there is an "unbox.any" in there, which the article states means:
    "Extract a value-type from obj, its boxed representation, and copy to the top of the stack."

    So that certainly suggests that there's an unboxing going on, which makes sense because that statement is syntactical sugar for:

    int i = 10;
    object o = i;
    if (o is int)
    {
        int j = (int)o;
        System.Console.WriteLine(j);
    }
    

    And this does have an explicit unboxing.

    Your second snippet produces this IL:

    IL_0000:  nop         
    IL_0001:  ldc.i4.s    0A 
    IL_0003:  stloc.0     // i
    IL_0004:  ldloc.0     // i
    IL_0005:  box         System.Int32
    IL_000A:  stloc.1     // o
    IL_000B:  ldc.i4.s    0A 
    IL_000D:  box         System.Int32
    IL_0012:  ldloc.1     // o
    IL_0013:  call        System.Object.Equals
    IL_0018:  stloc.2     
    IL_0019:  ldloc.2     
    IL_001A:  brfalse.s   IL_0029
    IL_001C:  nop         
    IL_001D:  ldstr       "It`s 10! "
    IL_0022:  call        System.Console.WriteLine
    IL_0027:  nop         
    IL_0028:  nop         
    IL_0029:  ret  
    

    You can see there is a "call" to "System.Object.Equals" that is being done on "o", but no unboxing required which suggests it's just doing a standard value-equality check.


0 additional answers

Sort by: Most helpful