tags:

views:

288

answers:

4

I have string which might be int, datetime, boolean, byte etc'.

How can i validate that the string can be convert into those types without using the TryParse of each type?

+3  A: 

Apart from calling Parse() inside a try catch block (a terrible idea), I think the only alternative is to write your own parsing algorithm (also a bad idea).

Why don't you want to use the TryParse methods?

AndrewS
because i have many possible types, so using the parsing/tryparsing is lots of code to write, so before use this ugly way, i'm looking for better one.
Tamir
I think you're in for a lot of if/else statements. I don't think there's really a cleaner way to do it.
AndrewS
+1  A: 

You can use regular expressions to determine what type they may be. Although it will be a little trickier if you need to differenciate between an int and a byte if the value is less than 255.

Mark
+2  A: 
public class GenericsManager
{
    public static T ChangeType<T>(object data)
    {
        T value = default(T);

        if (typeof(T).IsGenericType &&
          typeof(T).GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
        {
            value = (T)Convert.ChangeType(data, Nullable.GetUnderlyingType(typeof(T)));

        }
        else
        {
            if (data != null)
            {
                value = (T)Convert.ChangeType(data, typeof(T));
            }
        }

        return value;
    }
}

Not massively useful here, but i guess you could use this, and validate that the result is not equal to the default for that type.

However, tryparse is much better and to the point of what you are trying to do.

tim
this is exactly the solution type i was looking for.any way, I've already implement similar solution which is more compatible for my use:private bool IsTypeOf<T>(string value) where T : struct{if (string.IsNullOrEmpty(value)){ throw new ArgumentException("text can not be null or empty.", value);}bool isFromType = false;Type type = typeof(T);MethodInfo tryParse = type.GetMethod("TryParse", new Type[] { typeof(string), type.MakeByRefType() });if (tryParse != null){ isFromType = (bool)tryParse.Invoke(null, new[] { value, null });}return isFromType;}Thanks!
Tamir
You are using reflection for this?I am not really sure what you are trying to do with this, but reflection is a really expensive process to use for something that is just saving a few lines of code.I would almost prefer wrapping the ChangeType<T>(object data) method up with something like a try / catch (invalidcastexception) block - i think that is the correct exception off the top of my head, and returning the bool from the try /catch flow there. - Fully aware neither really a good thing to do though.
tim
A: 

You can use a mix between TryParse and regular expressions. It's not a pretty code, but is fast, and you can use the method everywhere.

There is a problem concerning Boolean type. 0 or 1 can be represent Boolean values, but also can be from type Byte. I parsed the true and false text values, but regarding your business rules your should decide what is best for you.

public static Type getTypeFromString(String s)
        {
            if (s.Length == 1)
                if (new Regex(@"[^0-9]").IsMatch(s)) return Type.GetType("System.Char");
            else
                return Type.GetType("System.Byte", true, true);

            if (new Regex(@"^(\+|-)?\d+$").IsMatch(s))
            {
                Decimal d;
                if (Decimal.TryParse(s, out d))
                {
                    if (d <= Byte.MaxValue && d >= Byte.MinValue) return Type.GetType("System.Byte", true, true);
                    if (d <= UInt16.MaxValue && d >= UInt16.MinValue) return Type.GetType("System.UInt16", true, true);
                    if (d <= UInt32.MaxValue && d >= UInt32.MinValue) return Type.GetType("System.UInt32", true, true);
                    if (d <= UInt64.MaxValue && d >= UInt64.MinValue) return Type.GetType("System.UInt64", true, true);
                    if (d <= Decimal.MaxValue && d >= Decimal.MinValue) return Type.GetType("System.Decimal", true, true);
                }
            }

            if (new Regex(@"^(\+|-)?\d+[" + NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator + @"]\d*$").IsMatch(s))
            {
                Double d;
                if (Double.TryParse(s, out d))
                {
                    if (d <= Single.MaxValue && d >= Single.MinValue) return Type.GetType("System.Single", true, true);
                    if (d <= Double.MaxValue && d >= Double.MinValue) return Type.GetType("System.Double", true, true);
                }
            }

            if(s.Equals("true",StringComparison.InvariantCultureIgnoreCase) || s.Equals("false",StringComparison.InvariantCultureIgnoreCase))
                return Type.GetType("System.Boolean", true, true);

            DateTime dateTime;
            if(DateTime.TryParse(s, out dateTime))
                return Type.GetType("System.DateTime", true, true); 

            return Type.GetType("System.String", true, true); 
        }
Ricardo