.NET
  Home arrow .NET arrow Page 7 - .NET Type System, Part II
ASP Free Forums 
.NET  
ASP  
ASP Code  
ASP.NET  
ASP.NET Code  
BrainDump  
C#  
Code Examples  
Database  
Database Code  
IIS  
Microsoft Access  
MS SQL Server  
Visual Basic.NET  
Windows Scripting  
Windows Security  
XML  
ASP Web Hosting  
ASP.NET Web Hosting 
Mobile Linux 
App Generation ROI 
Windows Web Hosting
 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
.NET

.NET Type System, Part II
By: Michael Youssef
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 36
    2005-03-28

    Table of Contents:
  • .NET Type System, Part II
  • C# Classes
  • Using Arrays
  • Single-Dimension Arrays
  • Multi-Dimension Arrays
  • C# Strings
  • Boxing Operation

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    .NET Type System, Part II - Boxing Operation


    (Page 7 of 7 )

    Sometimes you need to use a value type as a reference type, perhaps to pass it as an argument to a method parameter of type System.Object, and in many other scenarios. When you convert a value type instance to a reference type instance, it's a boxing operation; when you convert a reference type instance to a value type instance it's called an unboxing operation. Actually C# implicitly performs the boxing operation on your behalf, but you will need to explicitly perform the unboxing operation.

    To explain the boxing process I will write a simple program that declares a variable of type int and assigns the value 91 to this variable. It will also declare another variable of type System.Object (but I will use the C# keyword object; it's the same as System.String class and the keyword string analogy). Then I will assign the int variable to the object reference -- and this is exactly where the boxing operation happens. After that we will look at the MSIL code and see the IL Instruction box that does the magic for us. Compile the following code into a class, and then use the ILDASM tool to load the MSIL generated code as we have done in previous articles:

    using System;
    namespace Boxing
    {
    class BoxTest
    {
    static void Main(string[] args)
    {
    int x = 91;
    object xObject = x; // boxing happens here
    }
    }
    }

    Load the MSIL code and the namespace Boxing will be shown, as in the following figure (extend the hierarchy until you get to the Main method):

    Double click on the Main method and you will get the following MSIL code:

    .method private hidebysig static void Main(string[] args) cil managed
    {
    .entrypoint
    // Code size 11 (0xb)
    .maxstack 1
    .locals init ([0] int32 x,
    [1] object xObject)
    IL_0000: ldc.i4.s 91
    IL_0002: stloc.0
    IL_0003: ldloc.0
    IL_0004: box [mscorlib]System.Int32
    IL_0009: stloc.1
    IL_000a: ret
    } // end of method BoxTest::Main

    Okay that's good; the next step is to explain how the boxing process works, and then we will talk about the unboxing operation.

    The boxing operation begins with allocating memory on the Managed Heap (for the value type being boxed). Memory size for this boxed object is the same as the value type size plus the memory needed for .NET CLR internals like method invocation list tables and other information that is needed to form a reference type. Then the value of the value type is copied to this memory space on the Heap, and a reference (memory address) returns and gets stored on the Stack --and now you have a boxed value type. This happens automatically. Let's take a look at the MSIL code; I'm sure that you will like it.

    The first thing to notice is the .locals. It tells you that we have two local variables for the Main method, one of type int32 and the other of type object. The first instruction IL_0000: ldc.i4.s 91 loads a constant value; i4.s means load an integer value of 4 bytes. The value 92 is popped to (assigned to) our local variable (x) using the Instruction stloc.0. Note that the zero here means the first variable, which is x in our example.

    Now we have the value popped on the stack, so the instruction idloc.0 loads the value back, and now we can use the box instruction. The box instruction converts the value type, which in our example is type System.Int32, to a Reference Type. The stloc.1 is the most interesting Instruction in this example. As you know, the box instruction creates the object on the Managed Heap and returns a reference to that object. The Instruction stloc.1 requires the Common Language Runtime to pop the Boxing return value (which in this case is a reference to the newly created object on the Managed Heap) to the second local variable, which is xObject; now we have a reference to the object.

    Unboxing Operation

    I will extend the boxing example to explain the unboxing process. Copy the following code and compile it:

    using System;
    namespace Boxing
    {
    class BoxTest
    {
    static void Main(string[] args)
    {
    int x = 91;
    object xObject = x; // boxing happens here
    int y = (int) xObject; // Unboxing the xObject into a Value-Type
    }
    }
    }

     
    Load the file with the MSIL tool and extend the namespace, then double click on the Main method to get the MSIL code:

    .method private hidebysig static void Main(string[] args) cil managed
    {
    .entrypoint
    // Code size 19 (0x13)
    .maxstack 1
    .locals init ([0] int32 x,
    [1] object xObject,
    [2] int32 y)
    IL_0000: ldc.i4.s 91
    IL_0002: stloc.0
    IL_0003: ldloc.0
    IL_0004: box [mscorlib]System.Int32
    IL_0009: stloc.1
    IL_000a: ldloc.1
    IL_000b: unbox [mscorlib]System.Int32
    IL_0010: ldind.i4
    IL_0011: stloc.2
    IL_0012: ret
    } // end of method BoxTest::Main

    The first thing to notice about the C# code is the cast operation. We didn't perform casting with boxing because the CLR knows what to do, and it allocates the memory needed to contain the value of the value type. With unboxing, we must explicitly perform the cast operation back to the right type (in our example back to int) because object is a general type and it can be anything. The C# compiler needs to know exactly what type is needed for the unboxing operation, so the cast must be valid.

    Look at the .locals and you will see that there is a third variable (y) of type int that we used in the example for the unboxing. We will begin from the Instruction IL_000a: ldloc.1. This Instruction pushes or loads the value on the stack, and again 1 means the second variable which is the xObject. The unbox Instruction is used to convert the value on the stack from a reference type to a value type. Note that the value here is a reference (memory address) and the runtime will take care of converting the actual data (what the reference refers to) to a value type. 

    The last Instruction stloc.2 pops the value on the stack (in this case to the variable y) and the Main method returns.The unbox Instruction tests that the object variable (in our example xObject) refers to a valid object on the Managed Heap, and also tests that the value of this object can be converted to the specified value type that the cast is using. If it fails, the InvalidCastOperation exception is thrown. Note also that the boxed value is an independent copy, and changes to the original value type don't affect it; you can simply copy the boxed value back into a value type using the cast operator.


    DISCLAIMER: The content provided in this article is not warranted or guaranteed by Developer Shed, Inc. The content provided is intended for entertainment and/or educational purposes in order to introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent upon the reader to employ real-world tactics for security and implementation of best practices. We are not liable for any negative consequences that may result from implementing any information covered in our articles or tutorials. If this is a hardware review, it is not recommended to open and/or modify your hardware.

     

    .NET ARTICLES

    - Using CrystalReportViewer to Display Crystal...
    - Creating Summary .Net Crystal Reports
    - More on Commands, Input and the WPF
    - Grouping and Aggregating When Querying LINQ ...
    - Commands, Input and the WPF
    - Keyboard and Ink Input with WPF
    - Mouse Input and the WPF
    - Input with Windows Presentation Foundation
    - Introducing LINQ with XML and Databases
    - An Introduction to LINQ
    - Querying LINQ to SQL: Basics
    - Completing a Simple Storefront with LINQ
    - Knowing Your Environment: the System.Environ...
    - Creating the Home Page for a Simple Storefro...
    - LINQ Quickly with Language Integrated Queries





    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 6 hosted by Hostway
    Stay green...Green IT