Можно ли преобразовать экземпляр делегата в выражение Lambda?

Вот контекст моего вопроса:

Распространенным методом является объявление параметра метода как лямбда-выражения, а не делегата. Это сделано для того, чтобы метод мог исследовать выражение, чтобы делать интересные вещи, например узнавать имена вызовов методов в теле экземпляра делегата.

Проблема в том, что вы теряете некоторые интеллектуальные функции Resharper. Если параметр метода был объявлен как делегат, Resharper поможет при записи вызова этого метода, предложив вам с синтаксисом x => x указать значение аргумента для этого метода.

Итак ... возвращаясь к своему вопросу, я хотел бы сделать следующее:

    MethodThatTakesDelegate(s => s.Length);
}

private void MethodThatTakesDelegate(Func<string, object> func)
{
    //convert func into expression
    //Expression<Func<string, object>> expr = "code I need to write"

    MethodThatTakesExpression(expr);
}


private void MethodThatTakesExpression(Expression<Func<string, object>> expr)
{
    //code here to determine the name of the property called against string (ie the Length)
}

Я замалчивал эта запись в блоге, и, похоже, он просто выполняет прямое назначение. Разве это не сработает для вас?

plinth 21.01.2009 16:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
716
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я не верю, что здесь можно добиться того, чего вы хотите. Из комментариев в вашем коде похоже, что вы пытаетесь зафиксировать имя свойства, которому было присвоено значение в MethodThatTakesExpression. Для этого требуется лямбда-выражение дерева выражений, которое фиксирует контекст доступа к свойству.

Когда вы передаете делегата в MethodThatTakesDelegate, этот контекст теряется. Делегаты хранят только адрес метода, но не контекст информации о методе. Как только это преобразование будет выполнено, его невозможно вернуть.

Пример того, почему это невозможно, состоит в том, что может даже не существовать именованный метод, поддерживающий делегат. ReflectionEmit можно использовать для создания метода, который не имеет никакого имени и существует только в памяти. Однако можно назначить это объекту Func.

Нет, это невозможно.

Ответ принят как подходящий

Везде, где вы используете термин «лямбда-выражение», вы на самом деле имеете в виду «дерево выражений».

Лямбда-выражение - это бит в исходном коде, который

parameters => code

например

x => x * 2

Деревья выражений - это экземпляры класса System.Linq.Expressions.Expression (или, скорее, одного из производных классов), которые представляют код как данные.

Лямбда-выражения преобразуются компилятором в деревья выражений либо (или, скорее, в код, который генерирует дерево выражений во время выполнения) экземпляры делегатов или же.

Вы можете скомпилировать экземпляр LambdaExpression (который является одним из подклассов Expression) в делегат, но вы не можете пойти другим путем.

Теоретически мощь можно написать такой «декомпилятор» на основе IL, возвращаемого MethodBase.GetMethodBody в ситуациях некоторый, но в настоящее время существуют различные делегаты, которые не могут быть представлены деревьями выражений. Дерево выражений представляет собой выражение, а не утверждение или блок операторов, поэтому нет циклов, ветвлений (кроме условных выражений), присваивания и т. д. Я считаю, что это может измениться в .NET 4.0, хотя я бы не ожидал шага декомпиляции от Microsoft, если только для этого есть действительно веская причина.

Другие вопросы по теме