Generic Parse Method without Boxing

2019-03-15 07:11发布

I am trying to write a generic Parse method that converts and returns a strongly typed value from a NamedValueCollection. I tried two methods but both of these methods are going through boxing and unboxing to get the value. Does anyone know a way to avoid the boxing? If you saw this in production would you not like it, how bad is it for performance?

Usuage:

var id = Request.QueryString.Parse<int>("id");

Attempt #1:

public static T Parse<T>(this NameValueCollection col, string key)
{
    string value = col[key];

    if (string.IsNullOrEmpty(value))
        return default(T);

    if (typeof(T) == typeof(int))
    {
        //return int.Parse(value); // cannot convert int to T
        //return (T)int.Parse(value); // cannot convert int to T
        return (T)(object)int.Parse(value); // works but boxes
    }
    if (typeof(T) == typeof(long))
    {
        return (T)(object)long.Parse(value); // works but boxes
    }
    ...

    return default(T);
}

Attempt #2 (using reflection):

public static T Parse<T>(this NameValueCollection col, string key)
{
    string value = col[key];

    if (string.IsNullOrEmpty(value))
        return default(T);

    try
    {
        var parseMethod = typeof(T).GetMethod("Parse", new Type[] { typeof(string) });

        if (parseMethod == null)
            return default(T);

        // still boxing because invoke returns an object
        var parsedVal = parseMethod.Invoke(null, new object[] { value });
        return (T)parsedVal;
    }
    // No Proper Parse Method found
    catch(AmbiguousMatchException) 
    {
    }

    return default(T);
}

7条回答
欢心
2楼-- · 2019-03-15 07:51

For better readability, you could use a generic dictionary with an anonymous function as follows:

var parserFuncs = new Dictionary<Type, Func<string, object>>() {
    { typeof(int), p => (int) int.Parse(p) },
    { typeof(bool), p => (bool) bool.Parse(p) },
    { typeof(long), p => (long) long.Parse(p) },
    { typeof(short), p => (short) short.Parse(p) },
    { typeof(DateTime), p => (DateTime) DateTime.Parse(p) }
    /* ...same for all the other primitive types */
};

return (T) parserFuncs[typeof(T)](value);
查看更多
登录 后发表回答