Да, типы, которые можно проанализировать из строки, скорее всего, будут иметь статические перегрузки Parse
и TryParse
, которые вы можете найти с помощью отражения, как предложил Джон.
private static Func<string, T> GetParser<T>()
{
// The method we are searching for accepts a single string.
// You can add other types, like IFormatProvider to target specific overloads.
var signature = new[] { typeof(string) };
// Get the method with the specified name and parameters.
var method = typeof(T).GetMethod("Parse", signature);
// Initialize the parser delegate.
return s => (T)method.Invoke(null, new[] { s });
}
С точки зрения производительности - метод Invoke
принимает параметры метода как object[]
, что является ненужным выделением, и если ваши параметры включают типы значений, вызывает бокс. Он также возвращает object
, в результате чего результирующее число (при условии, что это также тип значения) помещается в коробку.
Чтобы противостоять этому, вы можете создавать лямбда-выражения:
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();
}
Вызов скомпилированного лямбда-выражения выполняется практически так же быстро, как и вызов исходного метода синтаксического анализа, но его создание и компиляция в первую очередь не так быстры. Вот почему, опять же, как предложил Джон, мы должны кэшировать полученный делегат.
Я использую статический универсальный класс для кэширования синтаксических анализаторов в ValueString.
private static class Parser<T>
{
public static readonly Func<string, T> Parse = InitParser();
private static Func<string, T> InitParser()
{
// Our initialization logic above.
}
}
После этого ваш метод разбора можно записать так:
public static T Parse<T>(string s)
{
return Parser<T>.Parse(s);
}
person
Şafak Gür
schedule
18.11.2017