Loring Software, Inc

A Software Developer's Notebook

I did some looking around for a good helper function for using TryParse to return a nullable type. There were a couple of examples, but nothing where you weren't writing a function for each type that had a TryParse. Even the example with generics had a specific implementation for each type.

So, I have written a generic version which uses reflection to try and call the generic type's TryParse. In this version, I just restrict the generic type to any value type, and return null if the type does not have a TryParse. But you could help protect calling with an invalid type, and get a compiler error instead, by limiting to the specific types which have a TryParse.

// helper function for nullable TryParse.  Only works with value types
private static T? TryParse<T>(string i_value) where T : struct
{
    // since the second parm for a TryParse is an out parameter, we
    // need to pass an object array with space reserved for the
    // out value.  I am passing its default value just to make me
    // feel comfortable, but null would have worked just as well
    object [] a_parms = new object[] { i_value, default(T) };
    try
    {
        // try and call a TryParse off the static members of this class.  If anything fails,
        // like the method does not exist, then they will get null
        if ((bool)typeof(T).InvokeMember("TryParse",
                            BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod,
                            null, null, a_parms))
           return a_parms[1] as T?;
    } catch {}
 
    return null;
}
 
 
DateTime? a_startDate = TryParse<DateTime>("1/1/11");
decimal? a_foo = TryParse<Decimal>("123.456");

Addendum:  I came across the IConvertible interface and ChangeType function in the .Net 4.0 Libraries this evening.  It simplifies the above code, and even allows you to pass things other than strings (any class which inplements IConvertible will do, including any complex class you write to implement it):

private static T? TryParse<T>(IConvertible i_value) where T : struct
{
    try  {
        return (T)Convert.ChangeType(i_value, typeof(T));
    }
    catch { } 

    return null;
}

So, not only do the above TryParse<T>(string) calls work, you can also do things like:

Boolean? a_res = TryParse<Boolean>(1);
int? a_res3 = TryParse<int>(false);

But the power still lies in converting strings, as in user input which may or may not exist.



Copyright © 2024 Loring Software, Inc. All Rights Reserved
Questions about what I am writing about? Email me