Generic type conversion FROM string

249

I have a class that I want to use to store "properties" for another class. These properties simply have a name and a value. Ideally, what I would like is to be able to add typed properties, so that the "value" returned is always of the type that I want it to be.

The type should always be a primitive. This class subclasses an abstract class which basically stores the name and value as string. The idea being that this subclass will add some type-safety to the base class (as well as saving me on some conversion).

So, I have created a class which is (roughly) this:

public class TypedProperty<DataType> : Property
{
    public DataType TypedValue
    {
        get { // Having problems here! }
        set { base.Value = value.ToString();}
    }
}

So the question is:

Is there a "generic" way to convert from string back to a primitive?

I can't seem to find any generic interface that links the conversion across the board (something like ITryParsable would have been ideal!).

This question is tagged with c# generics primitive type-safety

~ Asked on 2008-08-12 09:13:23

11 Answers


397

I am not sure whether I understood your intentions correctly, but let's see if this one helps.

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
        set { base.Value = value.ToString();}
    }
}

~ Answered on 2008-08-12 09:24:33


76

lubos hasko's method fails for nullables. The method below will work for nullables. I didn't come up with it, though. I found it via Google: http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx Credit to "Tuna Toksoz"

Usage first:

TConverter.ChangeType<T>(StringValue);  

The class is below.

public static class TConverter
{
    public static T ChangeType<T>(object value)
    {
        return (T)ChangeType(typeof(T), value);
    }

    public static object ChangeType(Type t, object value)
    {
        TypeConverter tc = TypeDescriptor.GetConverter(t);
        return tc.ConvertFrom(value);
    }

    public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
    {

        TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
    }
}

~ Answered on 2009-12-02 14:11:47


17

For many types (integer, double, DateTime etc), there is a static Parse method. You can invoke it using reflection:

MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}

~ Answered on 2008-08-12 09:32:06


9

TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptor is class having method GetConvertor which accept a Type object and then you can call ConvertFrom method to convert the value for that specified object.

~ Answered on 2013-07-09 11:26:13


3

Check the static Nullable.GetUnderlyingType. - If the underlying type is null, then the template parameter is not Nullable, and we can use that type directly - If the underlying type is not null, then use the underlying type in the conversion.

Seems to work for me:

public object Get( string _toparse, Type _t )
{
    // Test for Nullable<T> and return the base type instead:
    Type undertype = Nullable.GetUnderlyingType(_t);
    Type basetype = undertype == null ? _t : undertype;
    return Convert.ChangeType(_toparse, basetype);
}

public T Get<T>(string _key)
{
    return (T)Get(_key, typeof(T));
}

public void test()
{
    int x = Get<int>("14");
    int? nx = Get<Nullable<int>>("14");
}

~ Answered on 2015-08-07 17:53:00


3

With inspiration from the Bob's answer, these extensions also support null value conversion and all primitive conversion back and fourth.

public static class ConversionExtensions
{
        public static object Convert(this object value, Type t)
        {
            Type underlyingType = Nullable.GetUnderlyingType(t);

            if (underlyingType != null && value == null)
            {
                return null;
            }
            Type basetype = underlyingType == null ? t : underlyingType;
            return System.Convert.ChangeType(value, basetype);
        }

        public static T Convert<T>(this object value)
        {
            return (T)value.Convert(typeof(T));
        }
}

Examples

            string stringValue = null;
            int? intResult = stringValue.Convert<int?>();

            int? intValue = null;
            var strResult = intValue.Convert<string>();

~ Answered on 2019-03-13 08:00:42


3

You could possibly use a construct such as a traits class. In this way, you would have a parameterised helper class that knows how to convert a string to a value of its own type. Then your getter might look like this:

get { return StringConverter<DataType>.FromString(base.Value); }

Now, I must point out that my experience with parameterised types is limited to C++ and its templates, but I imagine there is some way to do the same sort of thing using C# generics.

~ Answered on 2008-08-12 09:23:51


0

Yet another variation. Handles Nullables, as well as situations where the string is null and T is not nullable.

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get
        {
            if (base.Value == null) return default(T);
            var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
            return (T)Convert.ChangeType(base.Value, type);
        }
        set { base.Value = value.ToString(); }
    }
}

~ Answered on 2017-08-07 21:26:54


0

I used lobos answer and it works. But I had a problem with the conversion of doubles because of the culture settings. So I added

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);

~ Answered on 2015-06-03 07:53:13


0

public class TypedProperty<T> : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

I using converting via an object. It is a little bit simpler.

~ Answered on 2010-12-17 14:51:24


-1

You can do it in one line as below:

YourClass obj = (YourClass)Convert.ChangeType(YourValue, typeof(YourClass));

Happy coding ;)

~ Answered on 2020-03-06 13:28:16


Most Viewed Questions: