|
Nope, I love that style of programming.
It's SO much more readable than a foreach/for/while loop.
It becomes immediately clear what the code does.
There's some collection than we need to filter, transform and process whereas a loop is just a loop and might do all those things, but you won't know until you read through the loop, probably with a lot more code to keep the new lists and counters. I've found a lot more unreadable loops than LINQ queries. I have no idea why you'd find it unreadable, it reads almost like natural language...
Anyway, that style is necessary for LINQ to SQL/Entities (because loops can't build expression trees, convert that to SQL and be lazy evaluated). And if I had to choose between LINQ or plain old SQL I'd choose LINQ wherever possible.
Only the .ForEach() is an odd one. It's defined on List<t> and not as a LINQ extension method because ForEach, by definition, has side-effects and LINQ was designed keeping the functional paradigm in mind. I never use it.
|
|
|
|
|
Sander Rossel wrote: I have no idea why you'd find it unreadable, it reads almost like natural language.. I think the problem is it's the wrong language for me. I don't think in terms of filters and transformations but this style forces me to.
|
|
|
|
|
I do think that way, but your style forces me not to. From now on I'll consider for loops a cancer
|
|
|
|
|
Sander Rossel wrote: It becomes immediately clear what the code does.
I think this is the important part. You focus on what the code does, without caring how this is done. As long as it does what it promises (which is the case with LINQ - usually) you're fine.
So you're abstracting away how you would (for example) filter the collection.
|
|
|
|
|
Yeah, and the how becomes so much more easier to read when you know what it is supposed to be doing in the first place
|
|
|
|
|
harold aptroot wrote: Is this style cancer?
No, next question.
harold aptroot wrote: why is this style popular?
Because it's superior to the other style. (I'm not talking about runtime performance here)
|
|
|
|
|
harold aptroot wrote: Is this style cancer? Absolutely!
A page full of IF...GOTO statements looks far more organised!
You don't even need ELSE s, or any of that indentation that makes the page a mess!
I wanna be a eunuchs developer! Pass me a bread knife!
|
|
|
|
|
When I started programming, "some" years ago, people where complaining about the performance of Object Oriented Programming (I won't speak of assembly vs. "high-level" language).
A "few" years later, when .NET arrived, the same was said regarding the use of the Framework compared to native code.
Nothing changes…
|
|
|
|
|
I didn't even mention performance, but sure, it aint great.
|
|
|
|
|
The "idea" isn't bad per say ... just that it tends to be taken too far.
Personally I try to keep such Linq chains down ... at most two dots in such a call (at least that being a quick-n-dirty rule-of-thumb). Especially as a normal for/foreach tends to be more efficient too, your sample is quite litterally performing 3 loops where one for loop would have sufficed.
The only time I feel such long chain of Linq extension methods make sense is if using the Linq SQL syntax instead. Though it's still not very efficient, actually less so than the pseudo FP style.
|
|
|
|
|
irneb wrote: your sample is quite litterally performing 3 loops where one for loop would have sufficed.
you should really take a look on what the compiler does when it enconters the yield keyword, you might be surprised to find out it's not as inefficient as you think.
|
|
|
|
|
Sentenryu wrote: you should really take a look on what the compiler does when it enconters the yield keyword
Not even slightly sure what you mean by that ???
Here's a test: BenchLinqLoops[^]
The chain of Linq statements clearly perform 3 loops (one of which is unnecessary). Yield doesn't "magically" fix that. And to show by how much such Linq chains (and even the Linq-to-SQL version) adds extra overhead - look at the performance of that yield function.
|
|
|
|
|
And just to make doubly sure no JIT optimizations skew the benchmark - I added an extra loop before starting the stopwatch, and rearranged the orders:
BenchLinqLoops[^]
Now you actually see the SQL variant's "extra" overhead - i.e. being translated into (effectively) the LinqAddXToEven2Loops function before it runs.
|
|
|
|
|
harold aptroot wrote: Is this style cancer?
No.
Linq has both it's Pro's and Con's. However, there is a clear benefit: Easy to write and easy to read (keep in mind that, if using Visual Studio, you have full intellisense support. And you can use your favourite code template, too.)
someStuff.Where(c => c != What).Select(d => d + The).Foreach(e => Hell(e));
looks better to me than
List<SomeStuff> tmpStuffList = new List<SomeStuff>();
for (int i = 0; i < someStuff.Count - 1; i++)
{
if (someStuff[i] != What)
{
tmpStuffList.Add(someStuff[i]);
}
}
for (int n = 0; n < tmpStuffList.Count - 1; n++)
{
Hell(tmpStuffList[n]);
}
I'll stick to the LinQ way of Querying.
|
|
|
|
|
Well, you did use some unnecessary stuff there.. temporary list isn't necessary, and those -1's should obviously not be there.
|
|
|
|
|
Sorting arrays in asp pages is ok I guess.
For business logic I would recommend an traditional approach.
so, yea, cancer for sure!
//ra
|
|
|
|
|
boss: "we need an else statement adding for when 'c' == Who and to run "Heaven(e)"
programmer: "right, that will be 2 hours."
foreach(var stuff in someStuff) {
if(stuff == What) {
Hell(stuff + The)
}
else if(stuff == Who) {
Heaven(stuff)
}
}
Boss: We all so need to call Devil() for when stuff it is "What".
|
|
|
|
|
harold aptroot wrote: Is this style cancer?
No.
harold aptroot wrote: Side question, why is this style popular?
It's part of the gradual shift from imperative programming to declarative programming. See also: javascript array functions.
|
|
|
|
|
We should be using that syntax because it's cleaner and more readable than lots of indented loops.
Our problems (at this point) are
- It's inefficient
- There's not enough good guidance on not doing dumb things (ToArray etc being case in point).
EF does a helluva job converting LINQ to SQL so what would be interesting is if there was a preprocesser that went through the whole LINQ chain, worked out what was really happening, then optimised (ie not did a bunch of stuff, parallelised other stuff, vectorised some stuff etc) and made it more efficient than foreach loops (which themselves are not efficient).
We shouldn't have a million devs optimising the same code. We should be able to express the code in elegant syntax and have the tools do the optimisation.
cheers
Chris Maunder
|
|
|
|
|
Plain-old-for definitely will work too, but this "one-liner" is specially intended for simple cases, where "for" is just too much!
Say, you need just checked checkboxes:
var chs = AllChBoxes.Where(box => box.IsCheched);
...and now look what you have to do with for:
var chs = new List<CheckBox>();
foreach(var ch in AllChBoxes)
if (ch.IsChecked) chs.Add(ch);
You write THREE lines (what is obviously more to read + more error prone) and achieved... even worse result, since IEnumerable in one-liner takes less memory (if needed at all).
So get your a$$ from the criocamera and study new way!
|
|
|
|
|
Here it's still obvious. It's the chaining where things start to get confusing.
Besides, I can't agree with your statement that you must create a list, after all you need those checkboxes in order to do something with them, you can most of the time just do that in the very same loop that checks them.
|
|
|
|
|
You said "for vs LINQ", I show you obvious case where you're not right. If you wanna just discuss how long LINQ can be - it's different question.
You don't understand word "materialized". If you use "for", you have to create physical list, where you keep your objects. In case of LINQ you have Enumerator, which will not take any object until you ask! It's important difference when you have billion objects, where half of 'em match your query. Enumerator just pass 'em one-by-one (keeping memory consumption low exactly for ONE ELEMENT), while your "for" takes all necessary memory at once.
|
|
|
|
|
Thornik wrote: You said "for vs LINQ", I did not, I showed an example of what I deem unreasonable. Using a single clause is still clear, if often unnecessary, though I like Max for example - there's a case where it really is simpler than an equivalent explicit loop.
Thornik wrote: You don't understand word "materialized". If you use "for", you have to create physical list, where you keep your objects. Oh you mean the source, sure. foreach it is then, problem solved.
|
|
|
|
|
You shown long LINQ query and start talking about "foreach". But even being that long, FORMATTING RULES.
someStuff.Where(c => c != What)
.Select(d => d + The)
.Foreach(e => Hell(e));
Oh you mean the source, sure. foreach it is then, problem solved.
Nope. You do not solve problem if you prepare list of objects thru foreach - you have to put 'em in a List<> (because hell knows how it will be used later). In case of LINQ you prepare just REQUEST (which takes zero memory), which later will enumerate any amount of objects. And BTW same request can be enumerated many times.
|
|
|
|
|
Thornik wrote: because hell knows how it will be used later So then it isn't the source, and it probably doesn't need to exist. Just act on it right then and there in the loop.
|
|
|
|