Objects in C#: Casting, Boxing, Unboxing, typeof

Discussion in 'C#' started by usmanmalik, Feb 5, 2014.

  1. usmanmalik

    usmanmalik New Member

    Joined:
    Dec 28, 2013
    Messages:
    19
    Likes Received:
    14
    Trophy Points:
    0
    In the articles on namespaces in C#, I explained in detail that .NET framework class library contains thousands of classes, interfaces and enumeration in hundreds of assemblies. These classes are related to each other. We also know that C# is a purely object oriented language. Object oriented programming is based on three pillars: Polymorphism, Inheritance, and Encapsulation. This is also collectively known as PIE. In framework class libraries, almost all the classes are related to each other via inheritance relation.

    There is always a base class for a set of related classes. For example, a drawing class might have a base class Drawing, that further contains classes like DrawSquare, DrawRectangle etc. We discussed inheritance in detail in our article on inheritance in C++. C# is a bit different, here every class has a base class. Even a class that is totally isolated and have no similar class will have a base class. This universal base class in C# .NET is called the Object class or what we commonly refer the Object type. This is our topic of discussion today. I will explain the details and usage of Object class and how it serves as the parent class to all the other classes in .NET framework class library.

    The Object Type



    The object type is a super class to all the .NET classes. The object type resides in System namespace and can be accessed as System.Object. Via Object type you can store object of any C# class in the variable of type Object. In order to further elaborate this concept, we will take help of an example.

    Note: All the code samples in this tutorial have been developed in VS 2010 with C#.

    Example1
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace CSharpTutorial
    {
        public class CustomStack
        {
            int index;
            object[] StackData = new object[15];
            public void pushdata (Object item)
            {
                StackData[index] = item;
                index++;
            }
            public object popdata()
            {
                index--;
                return StackData[index];
             
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                CustomStack stack = new CustomStack();
                Console.WriteLine("Pushing the data in stack ....");
                stack.pushdata("Go4Expert");
                string s;
                Console.WriteLine("Retrieving the data from stack ....");
                s = (string)stack.popdata();
                Console.WriteLine(s);
                Console.ReadLine();
            }
        }
    }
    
    Pay attention at the start of the code. Inside the namespace CSharpTutorial, which is also the name of the project we have declared a class named CustomStack. The class has two member variables: one integer index and an array of type object named stackdata. The class also contains two member methods pushdata and popdata. The pushdata adds the data to the first unoccupied array index and popdata removes data from the last occupied index of object type array stackdata.

    The pushdata member receives variable of type object as parameter, inside the pushdata method we stored this item at the first unoccupied index and then increment the index integer so that it now again points to the first unoccupied array index. The return type of pushdata method is void since we do not want it to return anything, it just stores item.

    The popdata method is used to remove data from the leading occupied index. Index before popping the data points to the first unoccupied index so we first decremented it so that it points to the last occupied index. Now when the item is removed from the last occupied index, the index variable again points to the first unoccupied array index.

    This is the basic principle of stack, last in first out. By implementing pushdata and popdata methods we have achieved this functionality.

    Now come inside the main method. This where object type plays its role. Inside the main method, we have first declared object of type CustomStack, named stack. We called its pushdata method and passed a literal string to it named “Go4Expert”, now this argument will be stored in the item parameter of type object in the pushdata parameter.

    Note, string is a different type while item is of different. Yet item is able to hold this string, this is due to the reason that base classes can hold the variable of child classes and since object class is the base class of all the variables in the .NET framework, therefore it is able to hold virtually any variable type. Thus, we are able to store string in item parameter of object type.

    Casting



    Down Casting

    Consider the following line of code in Example1, this is very interesting.

    Code:
    s = (string)stack.popdata();
    When the popdata() method is called, it will return an object type. Object type is base class whereas string ‘s’ is child class. In order to store a base class variable into child class, we have to explicitly cast the base class variable into the type into which we have to store the variable. The above line of code basically casts the return item of type object into type string. This is called down casting.

    Up Casting

    You must be wondering than why we haven’t convert the string into object type before storing it into the item variable of type object. The answer is we don’t need to cast the child variable to be stored in the parent variable. It is implicitly done by the .NET runtime. This is actually called up casting which is implicit in .NET.

    Therefore, In Example1, we saw that how we can use object type to store variables of all the other classes and then retrieve the data from object type via down casting. The output of the code in Example1 is as follows.

    Output1

    [​IMG]

    Boxing and Unboxing

    Object type is basically a reference type. All classes in C# are reference types. A very interesting phenomena in C# is that of boxing and unboxing.

    Boxing: Boxing basically refers storing a value type variable into a reference type. For example, when you store an integer in a reference type instance such as instance of object class, you are basically boxing the value type into integer type. Boxing is implicit like up casting.

    Unboxing

    Unboxing is the reverse of boxing. Unboxing refers to converting a reference type variable into a value type variable. For Example, converting an object into integer is unboxing. Unboxing is explicit like down casting. Example2, further explains these concepts.

    Example2

    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace CSharpTutorial
    {
        class Program
        {
            static void Main(string[] args)
            {
                object obj = 5; // Boxing
                Console.WriteLine(obj);
    
                int num = (int)obj; // unboxing
                Console.WriteLine(num);
    
                Console.ReadLine();
            }
        }
    }
    
    Example2 is extremely straight-forward; we have first stored 5 in object obj and then displayed it; this boxing.

    Next, we down casted the obj into int and displayed it. This is unboxing.

    Now modify the main method of Example2 as follows

    Code:
    object obj = 5; // Boxing
    Console.WriteLine(obj);
    int num = (int)obj; // unboxing
    Console.WriteLine(num);
    long num1 = (long)obj; // not possible will give error
    Console.WriteLine(num);
    Console.ReadLine();
    
    What we have done here is introduce following line of code
    Code:
    long num1 = (long)obj; // not possible will give error
    Console.WriteLine(num);
    
    The object obj here contains an integer value 5 and we are casting it into long. The compiler will throw an exception because during casting it will match that what is stored in object and if it matches with the mentioned casting type only then will it cast the variable. Therefore, if you replace the code in example one with the mentioned above the code will throw InvalidCastException.

    But you can do
    Code:
    long num1 = (int)obj;
    Console.WriteLine(num1);
    
    Because, casting Is being done from obj which contains integer to int type and int type can be stored in a long type variable without further casting.

    The typeof operator and GetType method

    C# is a strongly typed language. By a strongly typed language we refer to a language where type checking is done at compile time in addition to run time. In C# both static and runtime type checking is done. For example, you cannot store string in integer type; compiler will warn you before compilation and will not compile the code. This is static type checking. Similarly, runtime type checking takes place when you cast objects or during unboxing an object. Internally, compiler uses special methods that are called to match the types of objects that are being converted into each other. What happens internally is that all the C# types are represented as System.Type to the compiler. In order to get the type of object in your code, there are two ways.

    Example3
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace CSharpTutorial
    {
        public class CustomStack
        {
            public  int index;
            public object[] StackData = new object[15];
            public void pushdata(Object item)
            {
                StackData[index] = item;
                index++;
            }
            public object popdata()
            {
                index--;
                return StackData[index];
    
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                CustomStack stack = new CustomStack();
                Console.WriteLine(stack.GetType().Name);
                Console.WriteLine(typeof(CustomStack).Name);
                Console.WriteLine(stack.GetType() == typeof(CustomStack));
                Console.WriteLine(stack.StackData.GetType().Name);
                Console.WriteLine(stack.index.GetType().Name);
                Console.ReadLine();
           
            }
        }
    }
    
    Example3 is similar to Example3, we have the same CustomStack class but inside the main method we are getting type of this class and its member variables using GetType method and typeof operator. Remember, GetType method needs instance of class whereas typeof requires type itself. Consider following lines of code.

    1- Console.WriteLine(stack.GetType().Name);

    In the above line we call GetType() method on the stack object of CustomStack and then get its name.

    2- Console.WriteLine(typeof(CustomStack).Name);

    In this line we called typeof operator and passed the class name instead of the class instance. We again accessed its name property to display name.

    3- Console.WriteLine(stack.GetType() == typeof(CustomStack));

    These lines simply equate the GetType and typeof, if the types are same, the answer will be true.

    4- Console.WriteLine(stack.StackData.GetType().Name);
    Console.WriteLine(stack.index.GetType().Name);


    The above two lines obtain the type of StackData and index member variables of stack data class. Here StackData is array of type object and index is an integer.

    We have displayed the types of all of these classes and their members on the screening using Console.WriteLine function. The output of the Example3 is as follows.

    Output3

    [​IMG]

    We can see in the output that both GetType and typeof are able to fetch the type of the class. Also, both GetType and typeof have similar functionality as we can see that equating both results in True. Lastly, we access the type of StackData which has been printed as Object[] and finally the type of index has been printed as Int32.

    ToString Method

    ToString() method is a built in method for all .NET classes. This method is used to display the textual representation of any object. In most of the cases, this ToString method is overridden by the classes in order to customize its functionality. Consider Example4 for further understanind.

    Example4
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace CSharpTutorial
    {
        public class ToStringDemo
        {
            string name;
            public ToStringDemo(string name)
            {
                this.name = name;
            }
    
            public ToStringDemo()
            {
                // TODO: Complete member initialization
            }
            public override string ToString()
            {
                return name;
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
    
                int i = 5;
                Console.WriteLine(i.ToString());
                ToStringDemo stringdemo = new ToStringDemo("ToStringDemoClass");
                Console.WriteLine(stringdemo.ToString());
                Console.ReadLine();
            }
        }
    }
    
    In the Example4, we have ToStringDemo class; the class has a string type variable name which is initialized by the constructor. We have overridden the ToString() method to return the variable string name.

    Inside the main function we store integer 5 in integer type variable I and then call ToString() method on it which will internally convert integer 5 to string 5 and will display it. Then we have declared an instance stringdemo of class ToStringDemo and passed it a string. Then we called, ToString() method on this object of reference type which displayed the member variable name which we returned from the overridden ToString() method in ToStringDemo class.

    An important point to note here is that when ToString() method is overridden on value types like integer, no boxing takes place internally whereas when ToString() method is overridden in reference types, boxing takes place internally. Another very important point to note here is that if ToString() method is not overridden in reference types, it returns the type name. The output of Example4 is as follows.

    Output 4

    [​IMG]
     
    Last edited by a moderator: Jan 21, 2017
    shabbir likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice