Objects in C#: Casting, Boxing, Unboxing, typeof
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 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#.
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.
Consider the following line of code in Example1, this is very interesting.
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.
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 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.
Next, we down casted the obj into int and displayed it. This is unboxing.
Now modify the main method of Example2 as follows
But you can do
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.
In the above line we call GetType() method on the stack object of CustomStack and then get its 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.
These lines simply equate the GetType and typeof, if the types are same, the answer will be true.
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.
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 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.
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.
|All times are GMT +5.5. The time now is 12:27.|