C#:是否可以在匿名方法中声明局部变量?
匿名 C# 方法中可以有局部变量,即在下面的代码中我只想执行一次计数。
IQueryable<Enquiry> 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);
匿名函数有“let”吗?
更新: 请注意,我在此语句后添加了多个Where 子句,因此无法通过选择关闭。
/尼尔斯
Is is possible to have a local variable in an anonymous c# methods, i.e. in the following code I would like to perform the count only once.
IQueryable<Enquiry> 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);
Is there a "let" for anonymous functions?
Update:
Note that I'm adding several Where clauses after this statement so I can't close with a select.
/Niels
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
是的,为什么不?! 毕竟它是一个函数,只是匿名的!
示例:
或者:
所以您的代码可以写为:
更新:为了澄清有关注释的内容,了解匿名方法和 lambda 表达式之间的区别非常重要。 匿名方法就像普通方法一样,没有显式名称。 当你编译它时,编译器会为你生成一个具有奇怪名称的普通方法,因此它不会有任何特殊限制。 然而,匿名方法的一种表示形式是 lambda 表达式。 Lambda 表达式可以用几种不同的方式解释。 第一个是代表。 这样,它们就相当于匿名方法。 第二个是表达式树。 这种方式通常由 LINQ to SQL 和其他一些 LINQ 提供程序使用。 他们不会以任何方式直接执行你的表达式。 他们将其解析为表达式树,并使用该树作为输入数据来生成要在服务器上运行的等效 SQL 语句。 它不像方法一样执行,也不被视为匿名方法。 在这种情况下,您无法定义局部变量,因为无法将 lambda 解析为表达式树。
Yes, why not?! After all it's a function, just anonymous!
Example:
Or alternatively:
So your code can be written as:
UPDATE: To clarify things about the comment, it's important to know the difference between anonymous methods and lambda expressions. An anonymous method is just like a normal method, without an explicit name. When you compile it, the compiler generates a normal method with a weird name for you instead, so it will not have any special limitations. However, one representation of an anonymous method is a lambda expression. Lambda expressions can be interpreted in a couple different ways. The first is a delegate. In that way, they are equal to an anonymous method. The second is an expression tree. This way is normally used by LINQ to SQL and some other LINQ providers. They don't execute your expression directly by any means. They parse it as an expression tree and use the tree as input data to generate the equivalent SQL statement to be run on the server. It's not executed like a method and it's not considered an anonymous method. In that case, you can't define a local variable as it's not possible to parse the lambda as an expression tree.
是的,您可以在 Linq to 对象和 Linq to SQL 中完全执行您想要的操作。
Linq 中有一个
let
,允许您按照自己的意愿为查询中间的中间结果命名。 根据您的示例:顺便说一句,我认为您的原始示例在语法上存在一些错误,当
count
只是一个名称时更容易发现:Yes, you can do exactly what you want, in Linq to objects and Linq to SQL.
There is a
let
in Linq, allowing you to give a name to an intermediate result in the middle of your query, just as you want to. Based on your example:By the way, I think there was something syntactically erroneous about your original example, which is easier to spot when the
count
is just a name:如果您使用 Linq to SQL,您将无法使用 Mehrdad Afshari 的答案。 您的 LINQ 表达式需要是表达式树,而它们不支持匿名委托语法。
您也无法在其他地方创建委托并从 lambda 内部调用它 - Linq to SQL 只允许在查询正文中执行某些操作,而调用委托不是其中之一。
假设您使用 Linq to SQL(如您的示例所示),最好的选择是减少一个查询中的计数,然后捕获需要计数的查询中的计数变量。
If you're using Linq to SQL, you won't be able to use Mehrdad Afshari's answer. Your LINQ expressions need to be Expression Trees, and those don't support the anonymous delegate syntax.
Neither will you be able to create your delegate elsewhere and call it from inside the lambda - Linq to SQL only allows certain operations to be performed in the body of the query, and calling a delegate isn't one of them.
Your best bet, assuming you're using Linq to SQL (as it appears given your example), is to bring down the count in one query, then capture the count variable in the query that requires the count.
Where 方法采用 Func,因此您在第二部分中传递的内容实际上并不是一个方法,而只是一个 bool 表达式。 我的建议是有一个返回 bool 的实际方法,它接受您需要的参数,并且在调用Where 方法时您只需执行类似这样的操作Where(p=> MyMethod(p,...) )
The Where method takes a Func so what you're passing in there in the second part ins't actually a method, but just a bool expression. My suggestion would be to have an actual method that returns a bool, that takes in the paremeters you need, and in your call to the Where method you just do something like this Where(p=> MyMethod(p,...))
我遇到了类似的问题。 解决方案是创建自定义表达式树生成方法。
我在 MSDN 论坛上提出了我的问题。 请在此处查看问题和答案:重用Where表达式。
这可能会让您了解如何继续,但我必须承认自定义表达式树不适合胆小的人;-)
I've run into a similar problem. The solution is to create a custom expression tree generating method.
I asked my question on MSDN-forums. Please see the question and answer here: Reusing Where expressions.
This may give you an idea on how to proceed, but I must admit that custom expression trees are not for the faint-hearted ;-)
有了一点Scheme 的背景,您就会知道“let”只是定义 lambda 并调用它的语法糖。
有了这些知识,让我们看看如何做到这一点。
作为奖励,它看起来也像Scheme :)
免责声明:我没有测试这个片段,但没有理由它不工作。 就我个人而言,我只会使用 LINQ 中提供的“let”构造。
更新:
它不起作用...:(
With a little background in Scheme you would know that 'let' is just syntax sugar for defining a lambda and invoking it.
So with that knowledge, lets see how it can be done.
As a bonus, it looks like Scheme too :)
Disclaimer: I did not test this snippet, but there is no reason it should not work. Personally, I would just use the 'let' construct provided in LINQ.
Update:
It does not work... :(