Yes, types that can be parsed from a string are more likely to have Parse
and TryParse
static overloads, which you can find through reflection, as John suggested.
private static Func<string, T> GetParser<T>() {
For performance, you can also create lambda expressions that call them, because the Invoke
method accepts the parameters of the method as object[]
, which is an unnecessary distribution, and if your parameters include value types, it calls boxing. It also returns the result as an object
, which also calls boxing when your type is a value type.
private static Func<string, T> GetParser<T>() { // Get the method like we did before. var signature = new[] { typeof(string) }; var method = typeof(T).GetMethod("Parse", signature); // Build and compile a lambda expression. var param = Expression.Parameter(typeof(string)); var call = Expression.Call(method, param); var lambda = Expression.Lambda<Func<string, T>>(call, param); return lambda.Compile(); }
Calling a compiled lambda expression is essentially as fast as calling the most original parsing method, but creating and compiling it in the first place is not. That is why, again, as John suggested, we have to cache the delegate we received.
I am using a static generic class to cache parsers in a ValueString .
private static class Parser<T> { public static readonly Func<string, T> Parse = InitParser(); private static Func<string, T> InitParser() {
After that, your parsing method can be written as follows:
public static T Parse<T>(string s) { return Parser<T>.Parse(s); }
Εafak GΓΌr Nov 18 '17 at 11:25 2017-11-18 11:25
source share