Как создать старую лямбду для использования с построением выражений?

Начиная с С# 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