Как создать старую лямбду для использования с построением выражений?
Начиная с С# 6, lambdas теперь по умолчанию использует методы экземпляра и никогда не будет статичным (что, я полагаю, означает, что они всегда захватывают сейчас, что, я думаю, более эффективно [кажется, быстрее, учитывая дискуссии]).
Смотрите здесь: Почему лямбда без захвата изменилась с статичного в С# 5 на метод экземпляра на С# 6?
и здесь: Разница в оценке статического лямбда-выражения компилятора CSC и Roslyn?
Это вызывает проблемы с использованием lambdas при создании статического метода MethodInfos для вызовов методов выражения, таких как Expression.Convert(Expression, typeof({SomeType}), conversionMethodInfo);
Итак, каков новый способ сделать это? Я попытался использовать "статический" модификатор с lambdas, и он не работает. Для тех, кто не может представить такой код, это может быть один пример:
Func <T1,T2> converter = static v => ConvertT1ToT2(v); // ('T' is whatever type you want)
Expression.Convert(expression, typeof({SomeType}), converter.Method) // (error: converter.Method.IsStatic is false)
Да, очевидно, это не сработает.
Ответы
Ответ 1
Итак, каков новый способ сделать это?
Нет. Спектр никогда ничего не обещал о деталях реализации лямбда-выражений. Вот почему вы не должны зависеть от них. Это также почему Что нового в С# 6 не упоминает об этом.
Предполагая, что вам нужно использовать Expression.Convert
с пользовательским MethodInfo
, тогда вы должны продвигать лямбда в метод static
:
private static T2 Converter(T1 v)
{
return ConvertT1ToT2(v);
}
…
MethodInfo converter =
typeof(ThisType).GetMethod("Converter", BindingFlags.NonPublic | BindingFlags.Static);
// OR:
MethodInfo converter = ((Func<T1, T2>)Converter).Method;
Expression.Convert(expression, typeof(SomeType), converter)
Таким образом, вы не используете лямбда, поэтому он гарантирует, что MethodInfo
относится к методу static
.
Ответ 2
В случае, если другие хотят знать, в конце концов, мне пришлось продвигать (demote? lol) мои выражения на "Элементы функции с выражением", например:
// (class method)
static string _Convert(object obj) => (obj as SomeType)?.SomeProperty ?? ReturnSomethingElse;
то в моем методе тело:
Func<object, string> conversionDelegate = _Convert;
Expression exp = Expression.Convert(expression, typeof(SomeType), conversionDelegate.Method);
Редактирование: некоторые говорят об отсутствии захвата/статических lambdas здесь: https://github.com/dotnet/csharplang/issues/275