c# - 将 .net Func<T> 转换为 .net Expression<Func<T>>

标签 c# .net lambda expression func

使用方法调用很容易从 lambda 转换为表达式...

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

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

但我想将 Func 转换为表达式,只是在极少数情况下......

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());
}

不起作用的行给我编译时错误 Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>' .显式转换不能解决这种情况。是否有我忽略的执行此操作的工具?

最佳答案

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

相关事实

这就是为什么将 lambda 推向极致的语言(如 Lisp)通常更容易实现为解释器。在这些语言中,代码和数据本质上是同一件事(即使在运行时),但我们的芯片无法理解这种形式的代码,因此我们必须通过在其上构建解释器来模拟这样的机器理解它的人(Lisp 做出的选择,如语言)或在某种程度上牺牲能力(代码将不再完全等于数据)(C# 做出的选择)。在 C# 中,编译器允许将 lambda 解释为代码 ( Func<T> ) 和 数据 ( Expression<Func<T>> ) >编译时间。

关于c# - 将 .net Func<T> 转换为 .net Expression<Func<T>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31139300/

相关文章:

c++ - 删除 lambda 赋值运算符的基本原理?

c# - 将png文件存储为字符串

c# - WCF 和 Delphi - 我应该使用 bytes[] 还是字符串?

c# - 设置为最大化的 WinForm 在循环中出现得太早

c# - C#中使用UdpClient类如何接收UDP包

c++ - C++ lambda捕获结果

C# 没有碰撞边缘的贪吃蛇游戏

c# - 使用 Visual studio 2010 检测内存泄漏?

c# - 根据参数在 Razor 中切换 Case

node.js - 如何解析 lambda 中的事件参数?