How to add a ToNumber C# language extension method to the String class calling TryParse using reflection.

February 25, 2009

I don’t particularly like the way data conversion between strings and numbers is done in C#. Of course originally we had the Parse method on each type. The down side to that was that it raised an unnecessary exception which needed to be handled, together with the exception’s associated overhead.

 

Next came TryParse. It was far better, because instead of raising an exception, it simply returned a true or false as to whether the string was indeed the type that we were trying to convert to. We usually end up with something like the following code:

int intResult;
bool successfulIntParse = int.TryParse(inputString, out intResult);
if (successfulIntParse)
{
     //do something with intResult
}

We’ve been able to use ToString() on number types for some time, so why not turn it around and execute a ToNumber() method on any string type?

 

The problem, of course, is what to do when the data conversion fails. Value types can’t accept null values. Well, that’s if you really need value types. With the new nullable types, we can provide a ToNumber() method that returns the same type but as a Nullable form.

 

So using C# language extensions, I am able now able to do the following:           
 

string numberString = "12345";
int? intResult = numberString.ToNumber<int>();

The benefit here is that behind the scenes it is still performing the TryParse, however now I can declare a variable inline. If the parse fails, it simply returns a null.

 

Here is the code for my conversion method extension, funnily enough, called ToNumber.

// Copyright 2009, Software Clearing House Pty Ltd
using System;
using System.Reflection;
namespace StringExtensions
{
    public static class StringToNumberCastExtensions
    {
        public static T? ToNumber<T>(this string input) where T : struct
        {
            Type[] paramTypes = new Type[] { typeof(string), typeof(T).MakeByRefType() };
            MethodInfo method = typeof(T).GetMethod("TryParse", paramTypes);
            Object[] parameters = new Object[] { input, null };
            if (method != null)
            {
                bool val = (bool)method.Invoke(typeof(T), parameters);
                if (val == true)
                    return (T?)parameters[1];
            }
            return null;
        }
    }
}

Note the “where T : struct” statement. That’s how I force it to accept only value types.

 

I also use reflection to call the TryParse method on the particular type that is passed in.  Note that this routine shouldn’t bomb if the TryParse method doesn’t exist on the particular value type passed in. Instead, it will return null.                                  

So add this class to your project, include a usingStringExtensions; statement, and you get the benefit of being able to inline convert your strings to numbers.

I also tried to override the cast operator so that I could specifically cast a string to a number, such as

int? myNumber = (int?)”12345″;

but unfortunately C# language extensions doesn’t support extending on operators.

And if you could do this:

int? myNumber = “12345”;

and have it do the automatic conversion, well, that’d be too much like VB, wouldn’t it!