Here is an extension method for string that makes it easy - almost trivial - to convert the value held by the string into another type.

var s1 = "43";
int count = s1.As<int>();

var s2 = "Green";
Color foreground = s2.As<Color>();

var s3 = "10.2.44.0";
Version release = s3.As<Version>();

How does this work?

  • Check for the special case of conversion to a string, and just return the same value if required.
  • Use a TypeConverter to convert if one is available that can handle a string. This handles a bunch of simple types like int, bool, DateTime, TimeSpan, Color and most enum types.
  • If the target type has a constructor that takes a single string, create an instance by passing the value to that constructor. This handles some more complex classes like Version and provides another way for your own types to hook into the conversion process.

Because this method uses reflection, performance is relatively poor - you may not want to use it in its current form in the midst of a tight loop. Like all performance issues however, measure performance with a profiler before you make changes.

Here’s the source:

public static T As<T>(this string value)
{
    object v = value;

    // If a string, just return it
    if (typeof(T) == typeof(string))
    {
        return (T)v;
    }

    // Use a TypeConverter if one is available
    var converter = TypeDescriptor.GetConverter(typeof(T));
    if (converter != null && converter.CanConvertFrom(typeof(string)))
    {
        try
        {
            return (T)converter.ConvertFromString(value);
        }
        catch (Exception ex)
        {
            string failureMessage
                = string.Format(
                    CultureInfo.CurrentCulture,
                    "Failed to convert \"{0}\" to {1}: {2}",
                    value,
                    typeof(T).Name,
                    ex.Message);
            throw new InvalidOperationException(failureMessage);
        }
    }

    // Look for a constructor that takes a string
    var constructor 
        = typeof(T).GetConstructor(new[] { typeof(string) });
    if (constructor != null)
    {
        return (T)constructor.Invoke(new[] { value });
    }

    var message 
        = string.Format(
            CultureInfo.CurrentCulture, 
            "Cannot convert {0} into {1}", 
            value, 
            typeof(T).Name);
    throw new InvalidOperationException(message);
}

Comments

blog comments powered by Disqus