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
Next Post
Becoming a Better Developer  18 Sep 2014
Prior Post
FTP, Unicode and the inconvenient bug  28 Jun 2014
Related Posts
Guaranteed Progression  19 May 2018
Prefer declarative method names  03 Feb 2018
Using Premeditation  27 Jan 2018
With Relocation  20 Jan 2018
Using Consolidation  13 Jan 2018
Using Semantic Types  06 Jan 2018
Using Extension Methods  30 Dec 2017
Error Methods  25 Nov 2017
Pass implementations, not representations  14 Oct 2017
Avoiding the Singleton Pattern  22 Jul 2017
More smart-code posts »
Archives
August 2014
2014