snippetcsharpModerate
Parse a specified arithmetic type from string
Viewed 0 times
parsetypefromstringspecifiedarithmetic
Problem
This class has the responsibility of parsing a string to one of the primitive types:
While creating it, I have noticed that it'll be terribly ugly.
It basically should perform a
int, double, float, decimal... While creating it, I have noticed that it'll be terribly ugly.
It basically should perform a
TryParse of each primitive type and return the first that returns true, along with the parsed value.public static class PrimitiveParser
{
public static bool TryParse(Type targetType, string sourceValue, out object result)
{
result = null;
if (targetType == typeof(int))
{
int intResult;
var parseResult = int.TryParse(sourceValue, out intResult);
{
result = intResult;
return parseResult;
}
}
if (targetType == typeof(double))
{
double doubleResult;
var parseResult = double.TryParse(sourceValue, out doubleResult);
{
result = doubleResult;
return parseResult;
}
}
if (targetType == typeof(float))
{
float floatResult;
var parseResult = float.TryParse(sourceValue, out floatResult);
{
result = floatResult;
return parseResult;
}
}
/// ...
return false;
}
}Solution
I'd prefer to use a dictionary for this.
The
This approach support exensibility.
For example, imagine we have a class
Then the only thing you have to do is to append an item to the dictionary:
Let's test it:
private delegate bool TryParseDelegate(string text, out T value);
private static readonly Dictionary TryParsers = new Dictionary
{
{ typeof(int), (TryParseDelegate)int.TryParse },
{ typeof(float), (TryParseDelegate)float.TryParse },
{ typeof(double), (TryParseDelegate)double.TryParse }
};The
TryParse method:public static bool TryParse(string value, out T returnValue)
{
// Check if we have a parse method for T in the dictionary.
object parserObj;
if (TryParsers.TryGetValue(typeof(T), out parserObj))
{
TryParseDelegate parser = (TryParseDelegate)parserObj;
return parser(value, out returnValue);
}
// If no, fallback to IConvertible.
if (typeof(IConvertible).IsAssignableFrom(typeof(T)))
{
try
{
returnValue = (T)Convert.ChangeType(value, typeof(T));
return true;
}
catch { }
}
// No luck.
returnValue = default(T);
return false;
}This approach support exensibility.
For example, imagine we have a class
A:public class A
{
public static readonly A Zero = new A("Zero");
public static readonly A One = new A("One");
public readonly string Text;
private A(string text)
{
Text = text;
}
public static bool TryParse(string text, out A value)
{
switch (text.ToLower())
{
case "zero":
value = Zero;
break;
case "one":
value = One;
break;
default:
value = null;
return false;
}
return true;
}
public override string ToString()
{
return Text;
}
}Then the only thing you have to do is to append an item to the dictionary:
{ typeof(A), (TryParseDelegate)A.TryParse }Let's test it:
int i;
double d;
A a;
if (TryParse("123", out i))
Console.WriteLine($"i={i}"); // Prints i=123
if (TryParse("123.456", out d))
Console.WriteLine($"d={d}"); // Prints d=123.456
if (TryParse("ONE", out a))
Console.WriteLine($"a={a}"); // Prints a=OneCode Snippets
private delegate bool TryParseDelegate<T>(string text, out T value);
private static readonly Dictionary<Type, object> TryParsers = new Dictionary<Type, object>
{
{ typeof(int), (TryParseDelegate<int>)int.TryParse },
{ typeof(float), (TryParseDelegate<float>)float.TryParse },
{ typeof(double), (TryParseDelegate<double>)double.TryParse }
};public static bool TryParse<T>(string value, out T returnValue)
{
// Check if we have a parse method for T in the dictionary.
object parserObj;
if (TryParsers.TryGetValue(typeof(T), out parserObj))
{
TryParseDelegate<T> parser = (TryParseDelegate<T>)parserObj;
return parser(value, out returnValue);
}
// If no, fallback to IConvertible.
if (typeof(IConvertible).IsAssignableFrom(typeof(T)))
{
try
{
returnValue = (T)Convert.ChangeType(value, typeof(T));
return true;
}
catch { }
}
// No luck.
returnValue = default(T);
return false;
}public class A
{
public static readonly A Zero = new A("Zero");
public static readonly A One = new A("One");
public readonly string Text;
private A(string text)
{
Text = text;
}
public static bool TryParse(string text, out A value)
{
switch (text.ToLower())
{
case "zero":
value = Zero;
break;
case "one":
value = One;
break;
default:
value = null;
return false;
}
return true;
}
public override string ToString()
{
return Text;
}
}{ typeof(A), (TryParseDelegate<A>)A.TryParse }int i;
double d;
A a;
if (TryParse("123", out i))
Console.WriteLine($"i={i}"); // Prints i=123
if (TryParse("123.456", out d))
Console.WriteLine($"d={d}"); // Prints d=123.456
if (TryParse("ONE", out a))
Console.WriteLine($"a={a}"); // Prints a=OneContext
StackExchange Code Review Q#148566, answer score: 11
Revisions (0)
No revisions yet.