C#:是否可以在匿名方法中声明局部变量?

可以在匿名c#方法中使用局部变量,即在以下代码中我只想执行一次计数。

IQueryable linq = db.Enquiries; if(...) linq = linq.Where(...); if(...) linq = linq.Where(e => (x <= (from p in db.Orders where p.EnquiryId == e.Id select p).Count() && (from p in db.Orders where p.EnquiryId == e.Id select p).Count() <= y)); if(...) linq = linq.Where(...); var result = (from e in linq select e); 

匿名函数是否有“让”?

更新:请注意,我在此语句后添加了几个Where子句,因此无法使用select关闭。

/尼尔斯

我遇到了类似的问题。 解决方案是创建自定义表达式树生成方法。

我在MSDN论坛上问了我的问题。 请在此处查看问题和答案: 重复使用Where表达式 。

这可能会让你知道如何继续,但我必须承认自定义表达树不适合胆小的人;-)

是的,为什么不?! 毕竟它是一个function,只是匿名!

例:

  x => { int y = x + 1; return x + y; } 

或者:

  delegate(int x) { int y = x + 1; return x + y; } 

所以你的代码可以写成:

  ... = linq.Where(e => { var count = (from p in db.Orders where p.EnquiryId == e.Id select p).Count(); return x <= count && count <= y; }); 

更新:要澄清有关注释的内容,了解匿名方法和lambda表达式之间的区别非常重要。 匿名方法就像普通方法一样,没有明确的名称。 编译时,编译器会为您生成一个带有奇怪名称的普通方法,因此它不会有任何特殊限制。 但是,匿名方法的一种表示forms是lambda表达式。 Lambda表达式可以用几种不同的方式解释。 第一个是代表。 这样,它们就等于匿名方法。 第二个是表达式树。 这种方式通常由LINQ to SQL和其他一些LINQ提供程序使用。 它们不会以任何方式直接执行您的表达式。 它们将其解析为表达式树,并使用树作为输入数据来生成要在服务器上运行的等效SQL语句。 它不像方法那样执行,也不被认为是匿名方法。 在这种情况下,您无法定义局部变量,因为无法将lambda解析为表达式树。

是的,您可以完全按照自己的意愿,在Linq中使用对象,使用Linq to SQL。

Linq中有一个let ,允许您在查询中间为中间结果命名,就像您想要的那样。 根据您的示例:

 ... = from e in linq let count = (from p in db.Orders where p.EnquiryId == e.Id select p).Count() where (x <= count) && (count <= y) select e; 

顺便说一句,我认为你的原始例子在语法上是错误的,当count只是一个名字时更容易发现:

 where (x <= count) && /* <= */ (count <= y); 

如果你使用Linq to SQL,你将无法使用Mehrdad Afshari的答案。 您的LINQ表达式需要是表达式树,而那些不支持匿名委托语法。

你也不能在别处创建你的委托并从lambda内部调用它 – Linq to SQL只允许在查询体中执行某些操作,而调用委托不是其中之一。

假设您正在使用Linq to SQL(如您的示例所示),最好的办法是在一个查询中降低计数,然后捕获需要计数的查询中的count变量。

Where方法接受一个Func所以你在第二部分传递的内容实际上不是一个方法,而只是一个bool表达式。 我的建议是有一个实际的方法返回一个bool,它接收你需要的参数,并且在你调用Where方法时你只需要做这样的事情在哪里(p => MyMethod(p,…))

在Scheme中有一点背景知识,你会知道’let’只是用于定义lambda并调用它的语法糖。

因此,有了这些知识,让我们看看它是如何完成的。

 (count => x <= count && count <= y) ((from p in db.Orders where p.EnquiryId == e.Id select p).Count()) 

作为奖励,它看起来像Scheme 🙂

免责声明:我没有测试这个片段,但没有理由不应该工作。 就个人而言,我只会使用LINQ中提供的'let'结构。

更新:

这是行不通的... :(