Simon said:
[...]
My main suggestion: don't use LINQ unless it really adds something
useful to the code.
Hi Peter, can I get your views on this (and anyone elses for that matter)?
It seems to me that behind this suggestion is the implicit assumption of
serial/procedural coding. If you use LINQ by default are you not moving
away from that paradigm since you are working declaratively at a
slightly higher level of abstraction. [...]
I'm not sure it's a "higher level". It's certainly a slightly different
way to represent the logic. But inasmuch as much of LINQ (and certainly
the parts your original example is using) is simply a plain syntactical
search-and-replace, I don't see how I would call it "higher level". To
me, "higher level" implies that one is able represent a particular
operation in a more concise and/or more expressive way.
More concise should be obvious. We see this even in relatively simple
"high level languages", where control or looping statements get
translated into much more wordy, but much-less-obvious equivalents in
machine code.
More expressive is not always more concise (but IMHO usually is). But
it does mean that the "higher level" feature allows you to _express_ the
solution to a problem in a way that is closer to the real-world
framework of the problem.
LINQ shines in the latter way when you're doing things that are
naturally more like database queries than they are like plain old
iterative processing. You wind up being able to express the query
itself in a language that has a similar structure to that used for the
database, rather than having to wrap up the database language in some
non-database syntax (e.g. filling a .NET data structure with SQL query
strings).
An example of where LINQ can add a lot of benefit in both the "more
concise" and "more expressive" way is when using the System.Xml.Linq
namespace, where the design of the types in the namespace has been
carefully thought out to work very well with declarative-like code using
LINQ. The operations aren't database-like, but inasmuch as XML tends to
be a sort of declarative data structure-oriented thing, having a
declarative way to generate and process XML can be very useful.
In this newsgroup especially, I have seen a LOT of LINQ code examples
that were actually _less_ expressive and more difficult to write and
understand than the non-LINQ code would have been. They were written
just for the sake of implementing something in LINQ, rather than because
LINQ was actually improving the code somehow.
The code example you posted is in a sort of middle ground. There are at
least a couple of places where using LINQ may be viewed as beneficial:
being able to use "where" to filter the results of the previous
enumeration, and using "select" to essentially "project" those results
into a new form (the actual instances you'll use).
But on the other hand, LINQ is IMHO obfuscating other aspects of the
code: even the first "from" clause is potentially a little awkward, and
having the second one following the first is not expressive at all,
unless the reader is already a strong LINQ user. Otherwise, one might
have to stop and think "a normal 'from' pulls from an enumeration
following the 'from', but here we have a 'from' pulling from an
enumeration preceding the 'from'". And even then, that's not what's
really going on; the second "from" really does pull from an enumeration
that follows it, but that enumeration depends on the previous "from" in
a way that may not be immediately or directly apparent to the casual reader.
Within LINQ, that's a perfectly natural way to express things, but it
does not IMHO make the code more obvious to the casual reader.
Another issue IMHO is that you are using the LINQ expression
immediately, and converting it directly to a list. This does come up,
of course...it's not like it's a patently bad thing to do. But I feel
that LINQ is at its best when you're actually using it to declare
_queries_. If the query being declared has to be immediately executed
for it to be of any practical use, and the LINQ isn't otherwise adding
something to the expressiveness of the code, for me that's a sign that
perhaps LINQ wasn't really the appropriate tool for the job.
Anyway, that's just a very long way of saying: LINQ can be cool and fun
to use, but don't get carried away. The "old ways" still work fine, and
in many cases are a better way to present the algorithm you're implementing.
I do recognize that there are times when making a paradigm shift -- e.g.
using a completely different syntax to represent a given solution -- can
lead to a perceptive benefit that allows you to come up with a whole new
approach to solving a problem that is better in some way than the
previous approach. But, if someone can come in and trivially rewrite a
LINQ expression as a couple of "foreach" loops with an "if" and an
"Add()", the LINQ probably isn't adding much to the problem.
Just my two cents. And you know how much that's worth these days.
Pete