Monday, July 20, 2015

Difference between explicit casting and using the "as" operator in C#

He who does not ask, will not learn. I would not learn this, if I did not ask - something else.
Upon raising the following question in StackOverflow, I started devising the ideal solution I would like to see for the problem (in an ideal world, a place I have been inhabiting for the past 30 years, alone).

Then, the person who offered an answer to the question - made a side remark.
Well, it then quickly had me building up a fresh new question :-)
He suggested instead of performing a cast using the "as" operator, I should do it simply with (T).

Example: say x is variable of type "object", and some type T, then I had var z = x as T;
He stated I should have var z = (T) x;

At first I noted, with the characteristic stubbornness - "it's a matter of taste. I think "as" makes the intent clearer". Minutes later, after playing with the solution, I needed to cast a double type. And thus... thankfully, I learned something new :-)
    
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(GenericCaster<string>(12345));
            Console.WriteLine(GenericCaster<object>(new { a = 100, b = "string" }) ?? "null");
            Console.WriteLine(GenericCaster<double>(20.4));
            
            //prints:
            //12345
            //null
            //20.4

            Console.WriteLine(GenericCaster2<string>(12345));
            Console.WriteLine(GenericCaster2<object>(new { a = 100, b = "string" }) ?? "null");
            
            //will not compile -> 20.4 does not comply to the type constraint "T : class"
            //Console.WriteLine(GenericCaster2<double>(20.4));
        }

        static T GenericCaster<T>(object value, T defaultValue = default(T))
        {
            T castedValue;
            try
            {
                castedValue = (T) Convert.ChangeType(value, typeof(T));
            }
            catch (Exception)
            {
                castedValue = defaultValue;
            }

            return castedValue;
        }

        static T GenericCaster2<T>(object value, T defaultValue = default(T)) where T : class
        {
            T castedValue;
            try
            {
                castedValue = Convert.ChangeType(value, typeof(T)) as T;
            }
            catch (Exception)
            {
                castedValue = defaultValue;
            }

            return castedValue;
        }
    }
 
Bottom line: GenericCaster2 will not work with struct types. GenericCaster will.

No comments:

Post a Comment