将Func分配给表达式,反之亦然

Meh*_*taş 19 c# linq lambda expression func

我篡改了表达式,我在某些方面感到困惑

  1. 我们可以将相同的LamdaExpression分配给Expression和/或Func.但我们不能将Func分配给表达式(或表达式为Func).为什么我们不能这样做?我查找是否定义了Expression和Func之间的转换运算符但我找不到任何转换运算符.

    Func<int, int> sumFunc            = i => i + i;
    Expression<Func<int, int>> sumExp = i => i + i;
    
    // sumExp = sumFunc; // Cannot convert source type 'System.Func<int,int>' to target type 'System.Linq.Expressions.Expression<System.Func<int,int>>'
    // sumFunc = sumExp; // Cannot convert source type 'System.Linq.Expressions.Expression<System.Func<int,int>>' to target type 'System.Func<int,int>'
    
    Run Code Online (Sandbox Code Playgroud)
  2. 即使我们无法将LambdaExpression分配给对象.再说一遍,为什么我们不能这样做呢?

    // object o = i => i + i; // Cannot convert source type 'lambda expression' to target type 'object'
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我认为编译器有一些东西.如果是这样,我们可以编写那些以这种(令人困惑的)方式表现的自定义类型并利用某些东西.

Des*_*sty 30

关于C#语言规范,lambda表达式如

i => i + i
Run Code Online (Sandbox Code Playgroud)

是一个匿名函数.具有此分类的表达式可以隐式转换为兼容的委托类型或表达式树类型.这就是为什么你可以写两个

Func<int, int> sumFunc            = i => i + i;
Expression<Func<int, int>> sumExp = i => i + i;
Run Code Online (Sandbox Code Playgroud)

第一个是委托类型,第二个是表达式树类型.由于这些类型之间没有隐式转换,因此无法分配sumFunc = sumExp,反之亦然.但由于表达式树sumExp表示lambda表达式,因此您可以将该表达式编译为可执行委托并将其分配给sumFunc,因为这是一个兼容的委托:

sumFunc = sumExp.Compile();
Run Code Online (Sandbox Code Playgroud)

另一个方向是不可能的,因为委托不能轻易地"反编译"成表达式树.

你不能写的原因

object o = i => i + i;
Run Code Online (Sandbox Code Playgroud)

是,匿名函数本身没有值或类型,它只能转换为委托或表达式树类型.您必须告诉编译器您想要哪一个,因此您可以先将其转换,然后将结果分配给类型的变量object:

object sumFuncObject = (Func<int, int>) (i => i + i);
object sumExpObject = (Expression<Func<int, int>>) (i => i + i);
Run Code Online (Sandbox Code Playgroud)

关于您的上一个问题:您可以在复杂类型之间创建自定义隐式或显式转换,以便可以将此"魔力"应用于分配.有关详细信息,请参阅" 转换操作编程指南"