linq Expression<TDelegate> 赋值如何在语言语法级别上工作

bol*_*lov 4 c# linq delegates moq linq-expressions

TLDR:这是如何编译的?

class A{};
Expression<Func<A, int>> e = x => 24; // I don't understant what makes this compile
                                      // and what happens at this assignment
Run Code Online (Sandbox Code Playgroud)

最少要多少class E才能编译E e = x => 24;


一些调查

class E {};

E e = x => 24;
Run Code Online (Sandbox Code Playgroud)

Visual Studio 错误是“无法将 lambda 表达式转换为类型 'E',因为它不是委托类型”,这很令人困惑,因为据我所知,委托是这样声明的:

int delegate MyHandle();
Run Code Online (Sandbox Code Playgroud)

我没有找到任何任命class代表的方法。

此外,我查看了元数据Expression -> LambdaExpression -> Expression<TDelegate>,但无法确定哪些语法/声明使Expression<TDelegate>行为像委托一样。

我什至尝试创建自己的class E来模仿Expression<TDelegate>,但我什至无法编译该类

// basically a copy-paste of the metadata of `Expression<TDelegate>`
public sealed class E<TDelegate> : LambdaExpression
{

    public TDelegate Compile() => default(TDelegate);
    public TDelegate Compile(DebugInfoGenerator debugInfoGenerator) => default(TDelegate);
    public TDelegate Compile(bool preferInterpretation) => default(TDelegate);
    public Expression Update(Expression body, IEnumerable<ParameterExpression> parameters)
        => default(Expression);
    protected override Expression Accept(ExpressionVisitor visitor) => null;
}
Run Code Online (Sandbox Code Playgroud)

收到错误“'LambdaExpression' 不包含采用 0 个参数的构造函数”


上下文(可以跳过):

我正在开始使用起订量,因为我不能认为事情是理所当然的,所以我试图了解它是如何工作的/它是如何实现的。这是有关此问题的一系列调查的第一部分。

我现在特别想了解

public class A
{
    public virtual int Foo() => throw new NotImplementedException();
    public virtual int Bar() => throw new NotImplementedException();
}

var a = new Mock<A>();

a.Setup(x => x.Foo()).Returns(24); // ??
Console.WriteLine(a.Object.Foo());
Run Code Online (Sandbox Code Playgroud)

我想了解如何a 通过传递 lambda 来传递“方法 Foo”信息?据我所知,lambda 只是一个可调用对象,但不知何故神奇地a知道 lambda 的实际主体,即如果您通过x => 24x => x.Foo() + x.Bar()但会接受,则会抛出异常x => x.Foo()

我看到该Setup参数是类型,Expression<Func<A, int>>因此是我当前的问题。

Ben*_*igt 5

C# 规范对 ; 给予特殊处理System.Linq.Expressions.Expression<D>。您无法针对自己的类型获得相同的治疗。

表达式树允许将 lambda 表达式表示为数据结构而不是可执行代码。表达式树是 形式的表达式树类型的值System.Linq.Expressions.Expression<D>,其中D是任何委托类型。

资料来源:https ://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/types#expression-tree-types