locked
Convert or TryParse from string to T (generic) possible? work around?

    Question

  • I found it difficult to search the web and these forums for something similar to what I want to do.  Of course conversion examples pop up and then of course generics pop up, but not in the way I am trying (perhaps bad news).  I have put in my time on trying to figure this out, but perhaps a bit of help from fellow developers is what I need. ;)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
    	class Program
    	{
    		public static Dictionary<string, string> VariableValuePairDictionary { get; set; }
    		public static T TryMatch<T>(T inVariable, string inName)
    		{
    			try
    			{
    				string value = VariableValuePairDictionary[inName];
    				inVariable = TryParse(inVariable, value);
    			}
    			catch (KeyNotFoundException) { }
    
    			return inVariable;
    		}
    		public static T TryParse<T>(T inVariable, string inValue)
    		{
    			switch (Type.GetTypeCode(inVariable.GetType()))
    			{
    				case TypeCode.Int32:
    					//inVariable = Convert.ToInt32(inValue);
    					break;
    				case TypeCode.String:
    					//inVariable = inValue;
    					break;
    				case TypeCode.Single:
    					//inVariable = Convert.ToSingle(inValue);
    					break;
    
    				default:
    					throw new Exception("Blow up in fantastic ways!");					
    			}
    			return inVariable;
    		}
    		public static void Main(string[] args)
    		{
    			VariableValuePairDictionary = new Dictionary<string, string>()
    			{
    				{ "name", "bob" },
    				{ "age", "25" },
    				{ "lbs", "155.5f" }
    			};
    
    			string name = "";
    			int age = 0;
    			float lbs = 0.0f;
    
    			name = TryMatch(name, "name");
    			age = TryMatch(age, "age");
    			lbs = TryMatch(lbs, "lbs");
    		}
    	}
    }
    In the above code you will see three lines commented out.  These are where I want to parse what is in the value string and convert it to the T data type variable.  Of course I get complaints from the compiler when trying this.  Perhaps I am approaching this wrong.  However, the solution that I am trying to avoid is writing many functions to handle all of the data types.  This would result in method explosion (probably 30 or so methods).  If that is the only way then perhaps I must do it but I am willing to bet there is a better way.  

    The only post I found on here remotely close to this resulted in a DataType<T> class that basically wrapped the class.  The examples from those posts didn't really seem helpful in my situation and I played around with it for a while to see if I could divine a way to make it work.  Alas, no dice.  I include it below in case someone finds it useful.

    	public class DataType<T> where T : struct
    	{
    		#region ctors
    		public DataType()
    		{
    			Value = 0;
    			T t = default(T);
    			Initialize(t);
    		}
    		public DataType(T t)
    		{
    			Value = 0;
    			Initialize(t);
    		}
    		#endregion ctors
    
    		#region fields
    		public object Value { get; set; }
    		#endregion fields
    
    		#region methods
    		private void Initialize(T t)
    		{
    			Value = 0;
    			TypeCode typeCode = Type.GetTypeCode(t.GetType());
    
    			try
    			{
    				Convert.ChangeType(Value, typeCode);
    				SetType(t);
    			}
    			catch (Exception ex) 
    			{ 
    				Console.WriteLine(ex.Message);
    				Convert.ChangeType(Value, TypeCode.Empty);
    				SetType(t);
    			}
    		}
    		private void SetType(T t)
    		{
    			Value = default(T);
    			Convert.ChangeType(Value, t.GetType());
    			Value = t;
    		}
    		#endregion methods
    	}


    To reiterate, I would like to be able to TryParse/Convert from a string to T data type such as float, int, double, char, boolean, etc without having to create all the methods necessary to handle each of those cases.  In the case that the TryParse/Convert fails to convert to that data type, I don't mind either an exception or a bool to let me know.

    Thanks, 
    Scott


    Wednesday, January 13, 2010 8:33 AM

Answers

  • .NET has the notion of type descriptiors that allow you to do all kind of conversions from one type to the other. This saves you from altering the TryParse method every time a new type needs to be converted. Try rewriting it as follows:

    public static T TryParse<T>(string inValue)
    {
        TypeConverter converter =
            TypeDescriptor.GetConverter(typeof(T));
    
        return (T)converter.ConvertFromString(null,
            CultureInfo.InvariantCulture, inValue);
    }
    I hope this helps.
    Visit my blog: http://www.cuttingedge.it/blogs/steven/
    • Marked as answer by m0rdred13 Wednesday, January 13, 2010 4:34 PM
    Wednesday, January 13, 2010 1:55 PM

All replies

  • public static T TryParse<T>(T inVariable, string inValue)
    {
        switch (Type.GetTypeCode(inVariable.GetType()))
        {
            case TypeCode.Int32:
                inVariable = (T)(object)Convert.ToInt32(inValue);
                break;
            case TypeCode.String:
                inVariable = (T)(object)inValue;
                break;
            case TypeCode.Single:
                inVariable = (T)(object)Convert.ToSingle(inValue);
                break;
    
            default:
                throw new Exception("Blow up in fantastic ways!");
        }
        return inVariable;
    }
    
    Wednesday, January 13, 2010 9:00 AM
  • .NET has the notion of type descriptiors that allow you to do all kind of conversions from one type to the other. This saves you from altering the TryParse method every time a new type needs to be converted. Try rewriting it as follows:

    public static T TryParse<T>(string inValue)
    {
        TypeConverter converter =
            TypeDescriptor.GetConverter(typeof(T));
    
        return (T)converter.ConvertFromString(null,
            CultureInfo.InvariantCulture, inValue);
    }
    I hope this helps.
    Visit my blog: http://www.cuttingedge.it/blogs/steven/
    • Marked as answer by m0rdred13 Wednesday, January 13, 2010 4:34 PM
    Wednesday, January 13, 2010 1:55 PM