Casting and converting in C#

Όνομα: *
Το email μου: *
Email παραλήπτη: *
Μήνυμα: *
Τα πεδία με έντονους χαρακτήρες είναι υποχρεωτικά.
Δεν έχετε συμπληρώσει όλα τα απαιτούμενα στοιχεία Το email που δώσατε δεν είναι σωστό

This is my very first post. In this article I will analyze the essense of casting in c# and discuss various ways you can use in order to use your variables the way you want.

 

Getting Started

What is casting? Using casting is like telling the compiler to treat an object of type A, as having type B. The most common way to do this is including the new type in parenthesis right before the variable. Take a look at the following example.
 
    private double IntegerToDouble()
    {
        //Cast an integer to double 
        int inputInteger = 11;
        double outputDouble = (double)inputInteger;
 
        return outputDouble;
    }
 
In the example we tell the compiler to treat inputInteger as double and save its value in outputDouble. The method will return 11.0.
 
Now, try this one.
 
    private int StringToIntegerError()
    {
        //Cast a string to integer 
        string inputString = "12";
        int outputInteger = (int)inputString;
 
        return outputInteger;
    }
 
Here, we ask the compiler to treat a string as an integer. Even though it would seem reasonable to treat string "12" as the integer 12, the complier will show build error stating "Cannot convert type 'string' to 'int'". This is because the compiler has no way to realize that "12" is different than "twelve" or "XII" which would seem harder to be treated as integers. Later on, we will find other ways to turn a string into an integer. For now, let's see what happens if we try to cast our string to an integer using an object to help us. 
 
     private int StringToIntegerException()
    {
        //Casting a string to integer will throw an exception
        string inputString = "12";
        object objectString = (object)inputString;
        int outputInteger = (int)objectString;
 
        return outputInteger;
    }
 
Run this and you will get an InvalidCastException stating "Specified cast is not valid.". It seems we can not cast "different" types to one another this way. However, keep in mind that, trying this, we got ourselves an InvalidCastException. If we use a try- catch and get this exception, then we will be able to know that casting failed. For example.
 
    private int StringToIntegerHandleException()
    {
        //Let's handle the exception 
        string inputString = "13";
        object objectString = (object)inputString;
        int outputInteger;
        try
        {
            outputInteger = (int)objectString;
        }
        catch (InvalidCastException ex)
        {
            outputInteger = 13;
        }
 
        return outputInteger;
    }
 
If you paid attention to the previous examples it will be easy for you to guess the output of the following method.
    private int DoubleToInteger()
    {
        //Cast a double to integer 
        double inputDouble = 14;
        int outputInteger = (int)inputDouble;
 
        return outputInteger;
    }
 
This result will be 14. Quite right. And what about the following?
 
    private int DoubleToIntegerExplicitCast()
    {
        //Casting a double to integer will cause explicit casting 
        double inputDouble = 15.6;
        int outputInteger = (int)inputDouble;
 
        return outputInteger;
    }
 
The compiler will do its best to treat the 15.6 as an integer and return 15. As you can see that was not quite right.
 
There are two types of casting, implicit and explicit casting. In case of implicit casting, a variable can be treated as of a different type and there is no data loss. In implicit casting it is not necessary to include the new type before the variable. We can rewrite our first example this way.
 
    private double IntegerToDoubleImplicitCast()
    {
        //Cast an integer to double 
        int inputInteger = 156;
        double outputDouble = inputInteger;
 
        return outputDouble;
    }
 
This will work just fine because we know that a double can contain all the data an integer can have. However in the previous example we wanted to cast a double to an integer. That was a case of explicit casting. There was data loss as a double can contain data that cannot fit within an integer. We also had to include the new type within parenthesis in order to tell the compiler that even though we know there may be an error, we want to cast anyway.
 
 

The "is" operator

Let's take a break and take a look at an operator that, while not a pure casting operator, has much to do with this. "is" can be used to check if a variable can be cast to a specific type. "is" will be used after the variable and before the type we want to check.
 
    private bool IntegerIsObject()
    {
        //Check if an integer can be cast as an objec
        int inputInteger = 17;
        if (inputInteger is object)
            return true;
        else
            return false;
    }
 
The method returns true as an integer can be cast to an object. "is" condition will also return false if variable is null. So, what is the purpose of this operator? We use "is" when we want to know if a variable can be cast to a type, in order to cast it without throwing an exception. Check out the next example.
 
    private object CastIfPossible()
    {
        //Cast string if possible
        string inputString = "18";
         if (inputString is object)
            return (object)inputString;
        else
            return null;
    }
 
The "is"  and the "as" operator (which we will see right away) can be used only in variables of reference type.
 
 

The "as" Operator 

There are more than one ways to cast an object. Let's use the "as" operator. "As" will be used after the variable we want to cast, followed by the type we want it to be converted. For example.
 
    private object IntegerToObjectUsingAs()
    {
        //Cast an integer to object
        int inputInteger = 11;
        object outputObject = inputInteger as object;
 
        return outputObject;
    }
 
Now, if we tried to repeat our first example, integer to double, using as, we would get a build error.
 
    private double IntegerToDoubleUsingAs()
    {
        //Cast an integer to double 
        int inputInteger = 16;
        double outputDouble = inputInteger as double;
 
        return outputDouble;
    }
 
The error would say "The as operator must be used with a reference type or nullable type". We mentioned earlier that "as" can be used only against reference type variables. However double is a value type (a non-nullable value type).
 
The previous example where we used "is" to check the type of the variable using "as" would look like
 
 
 
    private object CastIfPossibleUsingAs()
    {
        //Cast string if possible
        string inputString = "18";
        if (inputString is object)
            return inputString as object;
        else
            return null;
    }
 
Using the "as" keyword is said to be much faster than direct casting.
 
 

Converting

 
 
What is converting and what is the difference between that and casting? Both ways will give as what we want but in a different way. Cast will use operators, convertions will use methods that do their best to give us what we want. 
 
Let's take a quick look at the System.Convert class. There are a bunch of methods which can help us convert variables from one type to another. For example System.Convert.ToDouble has methods that can return double out of 18 different types. You can use the System.Convert methods to convert between basic types but not between all types. In that case you would have to use casting. We can now repeat the previous examples where we used casting.
 
    private double IntegerToDoubleConversion()
    {
        //Convert an integer to double 
        int inputInteger = 19;
        double outputDouble = Convert.ToDouble(inputInteger);
 
        return outputDouble;
    }
 
This method returns 19.0. Now,here's  another example.
 
    private int StringToIntegerConversion()
    {
        //Convert a string to integer 
        string inputString = "20";
        int outputInteger = Convert.ToInt32(inputString);
 
        return outputInteger;
    }
 
In addition to the previous example this method returns 20. It seems that Convert.ToInt32 is a method that does much more than trying a simple cast. However in case the method will not make a successful conversion it will throw a FormatException, like in the following example.
 
    private int StringToIntegerConversionException()
    {
        //Convert a string to integer 
        string inputString = "twenty";
        int outputInteger = Convert.ToInt32(inputString);
 
        return outputInteger;
    }
 
Similar to casting, there are implicit and explicit conversions.
 
 
 

Parse and TryParse

 
There are still more ways to make a convertion. You can try Parse methods like in the following example. Parse methods are located within the System.<type> class for each type. We will use Int32 methods in the examples. The same principles however can be used to other types as well.
 
    private int StringToIntegerParsing()
    {
        //Parses a string to integer 
        string inputString = "21";
        int outputInteger = Int32.Parse(inputString);
 
        return outputInteger;
    }
 
We will get 21 as a result just like the Convert methods would do. Actually, Convert.ToInt32 invokes the Int32.Parse method. However convert will handle null values and return 0, while Parse will throw an ArgumentNullException. So, even if parsing might seem to be faster than converting, there are people who prefer converting, as it is safer to use.
 
However, there is another way to handle such an occasion, the TryParse method. TryParse is a bool method that returns true if Parse succeeds and false if it would throw an exception. This example shows how it works.
 
    private int StringToIntegerTryParse()
    {
        //Parses a string to integer using TryParse 
        string inputString = "22";
        int outputInteger;
        if(!Int32.TryParse(inputString, out outputInteger))
            //Execution will not reach this point as TryParse will return true
           outputInteger = 23;
 
        return outputInteger;
    }
 
Method returns 22 as TryParse will return true. On the contrary, the next example will return 23.
 
    private int StringToIntegerTryParseFalse()
    {
        //Parses a string to integer using TryParse 
        string inputString = "twenty-two";
        int outputInteger;
        if (!Int32.TryParse(inputString, out outputInteger))
            //Execution will reach this point as TryParse will return false
            outputInteger = 23;
 
        return outputInteger;
    }
 
 
 

ToString

 
The last thing to examine is the System.ToString method. So far, we know what the Convert.ToString() does. In case of String there is no String.Parse() method. Instead we get the System.ToString method. Similar to a Parse() method, System.ToString will throw a NullReferenceException. Using System.ToString the compiler tries to represent our object in the most suitable string form. Here is an example which converts a double to string.
 
    private string DoubleToString()
    {
        //Converts a double to string 
        double inputDouble = 24.5;
        string outputString = inputDouble.ToString();
 
        return outputString;
    }
 
 

Conclusion

 
C# offers far too many ways to cast/ convert a variable to another type. Picking the most suitable one depends on what you want to achieve. We examined direct casting, the use of the "as" and "is" operators. We went on studying converting and parse methods. Finally we took a look at the ToString method.
 
 
 
 
 

Πίσω στο BlogΕπόμενο

Σχόλια



    Γράψε το σχόλιό σου
    Όνομα: