This is my second attempt on the TryParse with the C# 3.0 Extension Methods.
I just noticed that I am copy-pasting a lot of the Integer and Boolean parsing in my current project. Maybe I just don't know any better but I ended up using TryParse this way:
int intParsed;
value= int.TryParse(reader["Value"].ToString(), out intParsed) ? intParsed : 0;
or a little bit simpler:
int intParsed= int.TryParse(reader["Value"].ToString(), out intParsed) ? intParsed : 0;
I will appreciate if somebody would show me simpler solution but so far it is as it is. I am stuck with .NET 2.0 for now, but would it be 3.5, I'd put together an extension method. It started as a pretty simple extension of a Int32 type, but quickly evolved to the more generic solution, which uses some kind of Duck Typing guessing:
public static class TryParseExtender
{
public static T LazyTryParse<T>(this T instance, object input)
{
Type type = typeof (T);
MemberInfo[] members = type.FindMembers(
MemberTypes.Method,
BindingFlags.Public | BindingFlags.Static,
(objMemberInfo, objSearch) => objMemberInfo.Name.Equals(objSearch.ToString()),
"TryParse"
);
foreach (MemberInfo info in members)
{
try
{
bool boolResult;
object[] paramArray=new[]{input, instance};
object objResult = ((MethodInfo) info).Invoke(instance, paramArray);
if (bool.TryParse(objResult.ToString(), out boolResult)) return (T)paramArray[1];
break;
}
catch {}
}
throw new ApplicationException(type+ " doesn't support TryParse");
}
}
It is not the prettiest code but does the job. Return statement assumes that types which expose TryParse are able to cast the Object type to themselves. Unfortunately the C# Extension Methods are not that powerful as the Ruby's
Monkey Patching and I am already far enough
into the Ruby to recognize what power (and elegance) I am missing.
Here is the test harness for the extension, which also shows the usage patterns (generic inference makes code look simpler):
[TestFixture]
public class TryParseExtenderTest
{
[Test]
public void TestIntParsing()
{
string input = "230";
int result = 0;
result = result.LazyTryParse(input);
Assert.AreEqual(230, result);
}
[Test, ExpectedException(typeof(ApplicationException),
ExpectedMessage = "System.String doesn't support TryParse")]
public void TestStringParsing()
{
int input = 230;
string result = "";
result = result.LazyTryParse(input);
Assert.AreEqual("230", result);
}
[Test]
public void TestBooleanParsing()
{
string input = "true";
bool result = true;
result = result.LazyTryParse(input);
Assert.AreEqual(true, result);
}
[Test]
public void TestDateTimeParsing()
{
string input = new DateTime(2008, 12, 1).ToString();
DateTime result = DateTime.Now;
result = result.LazyTryParse(input);
Assert.AreEqual(new DateTime(2008, 12, 1), result);
}
}