Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq mix extension and query syntax

Tags:

c#

linq

c#-4.0

I prefer to use extension methods for the basic LINQ operations: Where(), Select, but for complex Select(), SelectMany(), and especially OrderBy().ThenBy() statements I find the query syntax to be much more readable and natural.

Today I found myself with the following query:

from c in _myObject.ObjectsParent.ParentsEnumerable
                    .Where(c =>
                        c == anotherObject || c.Parent == anotherObject)
from q in c.MyObjectsEnumerable
orderby c.SortKey, q.Description
select new { Item = q, Text = c.Description + " -> " + q.Description };

Is it dangerous (for readability, maintainability, or any other reason) to mix query and extension syntax?

This has potential to be very subjective, if it is, I'm sorry if it doesn't meet the requirements for a good subjective question. Let me know if I can improve it!

like image 759
Chris Pfohl Avatar asked Mar 01 '11 15:03

Chris Pfohl


3 Answers

Is it dangerous (for readability, maintainability, or any other reason) to mix query and extension syntax?

The biggest danger I'd see is the potential addition of "surprise" in your code, especially when viewed by other developers.

From a compilation standpoint, the query syntax is translated directly into the extension method calls, so there isn't necessarily a technical problem here. However, this is potentially going to be adding extra method calls that wouldn't, at a first glance, be expected by many developers. This could lead to a potential maintainability problem.

That being said, if done sparingly and with good reason, I don't feel that there is a real problem with mixing the syntax. This is actually quite common - for example, if you want to write in query syntax, but need to fully evaluate, it's often wrapped in parenthesis with .ToList() added - or if you want to use PLINQ with query syntax, it's often from x in collection.AsParallel(), which is technically mixing syntax as well...

like image 131
Reed Copsey Avatar answered Nov 01 '22 04:11

Reed Copsey


You could do something like this to make things a little easier.

var firstQuery =  _myObject.ObjectsParent.ParentsEnumerable
                 .Where(c => c == anotherObject || c.Parent == anotherObject);

var secondQuery = from q in firstQuery.MyObjectsEnumerable
                  orderby firstQuery.SortKey, q.Description
                  select new { Item = q, 
                               Text = firstQuery.Description + " -> " + q.Description };

Now your queries aren't mixed

like image 43
msarchet Avatar answered Nov 01 '22 05:11

msarchet


This is kind of a judgment call, but many "best practice"-type questions tend to be, at least at first. My opinion is that you should use one or the other within a single statement. Not really for any "danger" inherent in mixing, but for clarity.

In this particular case, the where clause is very simple, and I would refactor it into query syntax.

There are however cases that cannot be elegantly expressed in query syntax. In cases where it is simply unavoidable to mix syntaxes, the queries would (again IMO) be more readable if you split out the method chain into its own variable, then simply referenced that variable in the query-syntaxed statement. Using yours as a model:

//The method chain can be pulled out as its own variable...
var filteredParents = _myObject.ObjectsParent.ParentsEnumerable
                    .Where(c => c == anotherObject || c.Parent == anotherObject);

//...which you can then substitute in a now purely query-syntax statement
from c in filteredParents
from q in c.MyObjectsEnumerable
orderby c.SortKey, q.Description
select new { Item = q, Text = c.Description + " -> " + q.Description };
like image 3
KeithS Avatar answered Nov 01 '22 05:11

KeithS