C# LINQ表达式API不提供创建变量的方法吗?

C# LINQ表达式API不提供创建变量的方法吗?,c#,linq,linq-expressions,custom-linq-providers,C#,Linq,Linq Expressions,Custom Linq Providers,我想验证我的假设,即LINQ表达式API没有任何方法来创建表示局部变量创建的表达式 换句话说,您不能创建表达式来表示: int local; 因为这是一个变量声明语句,API不支持lambdas语句。由LINQ表达式API(而不是委托实例)表示的lambda表达式可以使用的唯一状态是它接收的参数和通过闭包接收的捕获变量 我的假设(基于几个月的LINQ表达式API实践)正确吗?好吧,您可以使用声明包含局部变量的块 例如: using System; using System.Linq.Expre

我想验证我的假设,即LINQ表达式API没有任何方法来创建表示局部变量创建的表达式

换句话说,您不能创建表达式来表示:

int local;
因为这是一个变量声明语句,API不支持lambdas语句。由LINQ表达式API(而不是委托实例)表示的lambda表达式可以使用的唯一状态是它接收的参数和通过闭包接收的捕获变量

我的假设(基于几个月的LINQ表达式API实践)正确吗?

好吧,您可以使用声明包含局部变量的块

例如:

using System;
using System.Linq.Expressions;

public class Test
{    
    static void Main()
    {
        var x = Expression.Variable(typeof(int), "x");
        var assignment1 = Expression.Assign(x, Expression.Constant(1, typeof(int)));
        var assignment2 = Expression.Assign(x, Expression.Constant(2, typeof(int)));

        var block = Expression.Block(new[] { x }, new[] { assignment1, assignment2 });
    }
}
它构建了一个表达式树,相当于:

{
    int x;
    x = 1;
    x = 2;
}

C#编译器在lambda表达式到表达式树的转换中不使用此功能,据我所知,目前这些转换仍然局限于表达式lambda。

False。要做到这一点,存在一些重载

事实上,不能通过使用具有变量的C#编译器创建lambda表达式,但这是编译器的一个限制

所以你不能

Expression<Func<int>> exp = () => {
    int v = 1;
    return v;
};
表达式exp=()=>{
int v=1;
返回v;
};
但是你可以

var variable = Expression.Variable(typeof(int));
var lambda = Expression.Lambda<Func<int>>(
    Expression.Block(
        new[] { variable }, 
        Expression.Assign(variable, Expression.Constant(1)), 
        variable)); // With lambda expressions, there is an implicit
                    // return of the last value "loaded" on the stack
var variable=Expression.variable(typeof(int));
var lambda=表达式.lambda(
表达式块(
新[]{variable},
Expression.Assign(变量,表达式.常量(1)),
变量);//对于lambda表达式,有一个隐式
//返回堆栈上最后一个“加载”的值
因为这是一个变量声明语句,API不支持lambdas语句


这在.NET<4.0中是正确的。在.NET4.0中,Microsoft添加了
Expression
方法来构建方法体中几乎所有的内容(缺少一些“东西”),如不安全的代码关键字/运算符,此外还有原语,但没有复杂的构造,如
for
lock
,可以构建在其他构造之上)。请注意,这些添加的内容中有90%与LINQ to SQL/EF不兼容。

您的意思是.NET表达式树是否支持“表达式”中的声明?例如,如果您尝试
System.Linq.Expressions.Expression expr=()=>{int local;}(尝试从C#lambda构建表达式树),您会收到错误CS0834:具有语句体的lambda表达式无法转换为表达式树。所以它至少不支持C#lambda箭头。非常感谢。我现在很困惑。我还需要进一步调查。造成我混淆的原因是
RequiresCanWrite
方法中的代码,该方法是从
表达式.Assign
工厂方法中调用的。它确保赋值的左侧是参数、索引器(用于数组或属性)或成员访问表达式(属性或字段)。这让我想测试是否可以创建一个本地文件并分配给它。我看到
表达式的代码内部。变量
因子创建了一个参数表达式。我想在我输入更多评论之前再考虑一下。另一个混淆点是C#具有块作用域。那么,在块内创建的变量真的是局部变量吗?块在CLR中有自己的堆栈帧吗?@WaterCoolerv2:这是代码的表示形式-不是IL。在普通的C语言中,块通常不会有单独的堆栈帧……对不起,我应该先用“如果编译…”来回答我的问题。我得到的事实是,这些都是表示,而不是IL。@WaterCoolerv2:我建议你考虑一下你想要的“真正的局部变量”的确切含义,然后测试它……我希望我能标记出你的答案以及正确的答案。我觉得它非常有用。