转换.net Func T到.net表达式<Func>> [英] converting a .net Func<T> to a .net Expression<Func<T>>

查看:20
本文介绍了转换.net Func T到.net表达式<Func>>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用方法调用可以轻松地从 lambda 到表达式...

Going from a lambda to an Expression is easy using a method call...

public void GimmeExpression(Expression<Func<T>> expression)
{
    ((MemberExpression)expression.Body).Member.Name; // "DoStuff"
}

public void SomewhereElse()
{
    GimmeExpression(() => thing.DoStuff());
}

但我想把 Func 变成一个表达式,只有在极少数情况下......

But I would like to turn the Func in to an expression, only in rare cases...

public void ContainTheDanger(Func<T> dangerousCall)
{
    try 
    {
        dangerousCall();
    }
    catch (Exception e)
    {
        // This next line does not work...
        Expression<Func<T>> DangerousExpression = dangerousCall;
        var nameOfDanger = 
            ((MemberExpression)dangerousCall.Body).Member.Name;
        throw new DangerContainer(
            "Danger manifested while " + nameOfDanger, e);
    }
}

public void SomewhereElse()
{
    ContainTheDanger(() => thing.CrossTheStreams());
}

不工作的行给了我编译时错误 不能隐式转换类型 'System.Func<T>'到System.Linq.Expressions.Expression".显式转换不能解决这种情况.是否有我忽略的设施来执行此操作?

The line that does not work gives me the compile-time error Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'. An explicit cast does not resolve the situation. Is there a facility to do this that I am overlooking?

推荐答案

哦,这并不容易.Func 代表一个通用的 delegate 而不是一个表达式.如果有任何方法可以这样做(由于编译器所做的优化和其他事情,可能会丢弃一些数据,因此可能无法恢复原始表达式),那就是即时反汇编 IL并推断表达式(这绝非易事).将 lambda 表达式视为数据 (Expression>) 是 编译器 的魔法(基本上编译器在代码中构建表达式树而不是编译它到 IL).

Ooh, it's not easy at all. Func<T> represents a generic delegate and not an expression. If there's any way you could do so (due to optimizations and other things done by the compiler, some data might be thrown away, so it might be impossible to get the original expression back), it'd be disassembling the IL on the fly and inferring the expression (which is by no means easy). Treating lambda expressions as data (Expression<Func<T>>) is a magic done by the compiler (basically the compiler builds an expression tree in code instead of compiling it to IL).

这就是将 lambda 表达式推向极致的语言(如 Lisp)通常更容易实现为解释器的原因.在这些语言中,代码和数据本质上是一回事(即使在运行时),但我们的芯片无法理解这种形式的代码,因此我们必须通过在其上构建解释器来模拟这样的机器它在某种程度上理解它(Lisp 像语言一样做出的选择)或牺牲了力量(代码将不再完全等于数据)(C# 做出的选择).在 C# 中,编译器允许将 lambdas 解释为 code (Func) 和 data,从而给人一种将代码视为数据的错觉(Expression>)在编译时.

This is why languages that push lambdas to the extreme (like Lisp) are often easier to implement as interpreters. In those languages, code and data are essentially the same thing (even at run time), but our chip cannot understand that form of code, so we have to emulate such a machine by building an interpreter on top of it that understands it (the choice made by Lisp like languages) or sacrificing the power (code will no longer be exactly equal to data) to some extent (the choice made by C#). In C#, the compiler gives the illusion of treating code as data by allowing lambdas to be interpreted as code (Func<T>) and data (Expression<Func<T>>) at compile time.

这篇关于转换.net Func T到.net表达式&lt;Func&gt;&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆