Denis Gladkikh
Russian   |  English

Method extension for safely type convert

Recently I read good Russian post with many interesting extensions methods after then I remembered that I too have one good extension method “Safely type convert”. Idea of this method I got at last job.

We often write code like this:

int intValue;
if (obj == null || !int.TryParse(obj.ToString(), out intValue))
    intValue = 0;

This is method how to safely parse object to int. Of course will be good if we will create some unify method for safely casting.

I found that better way is to create extension methods and use them then follows:

int i;
i = "1".To<int>();
// i == 1
i = "1a".To<int>();
// i == 0 (default value of int)
i = "1a".To(10);
// i == 10 (set as default value 10)
i = "1".To(10);
// i == 1
// ********** Nullable sample **************
int? j;
j = "1".To<int?>();
// j == 1
j = "1a".To<int?>();
// j == null
j = "1a".To<int?>(10);
// j == 10
j = "1".To<int?>(10);
// j == 1

Realization of this approach:

public static class Parser
{
    /// <summary>
    /// Try cast <paramref name="obj"/> value to type <typeparamref name="T"/>,
    /// if can't will return default(<typeparamref name="T"/>)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static T To<T>(this object obj)
    {
        return To(obj, default(T));
    }
 
    /// <summary>
    /// Try cast <paramref name="obj"/> value to type <typeparamref name="T"/>,
    /// if can't will return <paramref name="defaultValue"/>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="obj"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static T To<T>(this object obj, T defaultValue)
    {
        if (obj == null)
            return defaultValue;
 
        if (obj is T)
            return (T) obj;
 
        Type type = typeof (T);
 
        // Place convert to reference types here
 
        if (type == typeof(string))
        {
            return (T)(object)obj.ToString();
        }
 
        Type underlyingType = Nullable.GetUnderlyingType(type);
        if (underlyingType != null)
        {
            return To(obj, defaultValue, underlyingType);
        }
 
        return To(obj, defaultValue, type);
    }
 
    private static T To<T>(object obj, T defaultValue, Type type)
    {
        // Place convert to sructures types here
 
        if (type == typeof(int))
        {
            int intValue;
            if (int.TryParse(obj.ToString(), out intValue))
                return (T)(object)intValue;
            return defaultValue;
        }
 
        if (type == typeof(long))
        {
            long intValue;
            if (long.TryParse(obj.ToString(), out intValue))
                return (T)(object)intValue;
            return defaultValue;
        }
 
        if (type == typeof(bool))
        {
            bool bValue;
            if (bool.TryParse(obj.ToString(), out bValue))
                return (T)(object)bValue;
            return defaultValue;
        }
 
        if (type.IsEnum)
        {
            if (Enum.IsDefined(type, obj))
                return (T)Enum.Parse(type, obj.ToString());
            return defaultValue;
        }
 
        throw new NotSupportedException(string.Format("Couldn't parse to Type {0}", typeof(T)));
    }
}

This realization isn’t full – this is small method part, I use it at my site engine. It can work with int, long, bool, string, enums (with Nullable type of this types too). I think that you can add types very easy for this method (don’t forget about culture).

Obviously this approach you can use just inside of developers group, because It is not obviously why this method can’t cast any type A to type B.

kick it on DotNetKicks.com Shout it


You might also like

rss twitter

Comments (4)

Byron Regodon ( ) #
avatar
wow... this is very helpful.. thanks for the tip.
Denis Gladkikh ( ) #
avatar

Byron, I found little easy realization (and more powerful), use this last method in Parser class



private static T To<T>(object obj, T defaultValue, Type type)

{
    if (type.IsEnum)

    {
        if (Enum.IsDefined(type, obj)) return (T) Enum.Parse(type, obj.ToString());
        return defaultValue;
    }
 
    try
    {
        return (T) Convert.ChangeType(obj, type);
    }
    catch (Exception e)
    {
        // Log exception
        return defaultValue;
    }
}
Luke Lowrey ( ) #
avatar
Extension methods ftw. This will be great for parsing query string params.
Denis Gladkikh ( ) #
avatar
Luke, yep. I use it for my site :)
Submit Comment

If you want to get notifications about new comments at this topic, please fill email text box and check proper item. If you want to place source code in comment body place it in tags [code]...[/code], you can set language like this [code cs]...[/code], where cs can be cs, html, xml, java, js, php, sql, cpp, css.

 

busy