Say I have a method that takes an int as a string and returns the int if the parse succeeds or a null value otherwise.
int? ParseValue(string intAsString)
{
int i;
if (int.TryParse(intAsString, out i))
return i;
return null;
}
How can this method be re-written so that it works not only with int?, but also long?, decimal? and DateTime? ?
Also, we cannot simply return null from a generic method like in normal method. Below is the error that a generic method will throw if we are trying to return null. So, to return a null or default value from a generic method we can make use default().
Nullable types are a feature of some programming languages which allow a value to be set to the special value NULL instead of the usual possible values of the data type.
You typically use a nullable value type when you need to represent the undefined value of an underlying value type. For example, a Boolean, or bool , variable can only be either true or false . However, in some applications a variable value can be undefined or missing.
The nullable type can only be used with value types and not with reference types. So, we cannot use nullable with string.
It's funny you should mention it because I was messing around with something just like this the other day:
using System;
using System.Reflection;
static class Example
{
public static Tuple<Boolean, T?> TryParse<T>(this String candidate)
where T : struct
{
T? value = null;
Boolean success = false;
var parser = ParsingBinder<T>.GetParser();
try
{
value = parser(candidate);
success = true;
}
catch (FormatException) { }
return new Tuple<Boolean,T?>(success, value);
}
}
static class ParsingBinder<T>
{
static Func<String, T> parser;
public static Func<String, T> GetParser()
{
if (parser == null)
parser = getParser();
return parser;
}
static Func<String, T> getParser()
{
MethodInfo methodInfo
= typeof(T).GetMethod(
"Parse", new [] { typeof(String) });
if (methodInfo == null)
throw new Exception(
"Unable to retrieve a \"Parse\" method for type.");
return (Func<String, T>)Delegate
.CreateDelegate(typeof(Func<String, T>), methodInfo);
}
}
It is a similar approach but think of it like a better TryParse
method that returns a Tuple<Boolean, T?>
(this requires .NET 4). The first property of the tuple is a boolean value indicating the success or failure of the parsing attempt and the second property is a nullable value typed to the generic type argument that will be null
if parsing fails and the value if parsing succeeds.
It works by using reflection to retrieve a static Parse(String)
method from the generic type argument and invokes that method for the string that is passed in. I built it as an extension method to allow you to do stuff like this:
var intValue = "1234".TryParse<Int32>();
var doubleValue = "1234".TryParse<Double>();
Unfortunately this won't work on enums
since they don't have the same signature for the parse method so you couldn't use this extension to parse an enum
but it wouldn't be hard to hack this up to make a special case for enums.
One of the nice things about this approach is that the cost of retrieving the Parse
method via reflection is only incurred on the first use since a static delegate is created for all subsequent uses.
One more thing - the only thing that is clunky about this approach is that there is no language extensions or syntactic sugar that would make this easy to work with. What I was hoping to achieve with this code was a less clunky way of using the standard TryParse
methods that exist in the BCL.
I personally find this pattern rather ugly:
Int32 value;
if (Int32.TryParse(someString, out value))
// do something with value
mainly because it requires a variable declaration ahead of time and the use of an out
parameter. My approach above isn't really that much better:
var result = someString.TryParse<Int32>();
if (result.Item1)
// do something with result.Item2
What would be really cool would be to see a C# language extension that was built to work with a Tuple<Boolean, T?>
that would allow us to work with this type smoothly but I get the feeling the more I write about this that it doesn't really seem that feasible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With