Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Is it possible to declare a local variable in an anonymous method?

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

like image 692
Niels Bosma Avatar asked Dec 15 '08 18:12

Niels Bosma


2 Answers

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:

... = 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;

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:

where (x <= count) && /* <= */ (count <= y);
like image 174
Daniel Earwicker Avatar answered Oct 03 '22 00:10

Daniel Earwicker


Yes, why not?! After all it's a function, just anonymous!

Example:

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

Or alternatively:

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

So your code can be written as:

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

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.

like image 27
mmx Avatar answered Oct 03 '22 01:10

mmx