|
You'll note that Harold original code line
someStuff.Where(c => c != What).Select(d => d + The).Foreach(e => Hell(e));
won't actually work. To get it to compile, you'd need to change it to :
someStuff.Where(c => c != What).Select(d => d + The).ToList().Foreach(e => Hell(e));
which is I think, the type of thing PIEBALDconsult was referring to.
Truth,
James
|
|
|
|
|
Unless they had an extension method that implemented ForEach on IEnumerable<T> .
|
|
|
|
|
PIEBALDconsult wrote: Many fans of that style don't realize how many times the data gets copied and iterated when they do nonsense like that.
Many fans do realize, we just don't care
Would I use the style for loops that should be executed milion times a second, like image processing? No.
Would I use it for everything else? Hell yes.
|
|
|
|
|
Then you're not the problem.
|
|
|
|
|
Why? A for loop tends to be far clearer and easier to read, not to mention faster and more efficient.
|
|
|
|
|
obermd wrote: A for loop tends to be far clearer and easier to read
Because that's your opinion and when I code I don't take your opinions into account
|
|
|
|
|
PIEBALDconsult wrote: how many times the data gets copied and iterated
Iterated: yes.
Copied: only if you use ToList / ToArray / ToDictionary / etc.
That's the big benefit of lazy evaluation - nothing gets iterated or copied until you're ready to use it.
Of course, if you don't understand what you're doing, that can also the big drawback.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Exactly. The point being that many do not realize what they're doing.
|
|
|
|
|
I would argue the total opposite. This is not cancer. The data does not get copied and iterated because this is all lazy processed. Perhaps you dont understand how these methods actually work.
Do you know how many times it took me hours to construct a proper nested for loop? With this style the complex can be accomplished in minutes.
You need to call ToList when you are complete to finally iterate over the entire IEnumerable. Because the Where and Select methods are lazy processed I have found that you dont get the proper results at the end unless you call ToList.
Also calling ToList is needed when performing async or multi threaded code. You need your own copy of the items to mess with otherwise you will get errors.
As for performance we are talking small milliseconds longer.
I can read and understand that one liner perfectly in 5 seconds. Can you honestly say that a for loop is perfectly understandable in that amount of time? I think not.
Also did you know you can iterate over thousands of records in the same amount of time it takes to do an if(x == y) statement. "if" comparisons are the slowest code to run.
|
|
|
|
|
For reference, a branch misprediction is less than 20 cycles on any reasonable µarch (ie excluding NetBurst), you can't do thousands of anything in that time.
|
|
|
|
|
Another issue is trying to debug it. If you get an error or exception then it's harder to debug when it's effectively a single statement.
harold aptroot wrote: Side question, why is this style popular?
I worked with someone that used linq wherever possible. His argument was that it was "faster". I think people think that because something is new it's fast *shrug*
|
|
|
|
|
That's really weird, I would have thought that anyone who likes speed tests to see how fast it really is, or at least looks up someone elses test.. and then they'd never use this style again.
|
|
|
|
|
Or you know, some one can be aware of the costs and still make decision to use this style? Almost as if speed is not top priority all the time. In parts that you really care about performance - write it in C++, slap managed wrapper around and call it a day. For everything else - enjoy modern1 features which make your life easier.
1 - if you can call something that is 10 years modern, in programming world.
|
|
|
|
|
Yes, but you can't use this style for speed, because it doesn't offer that.
|
|
|
|
|
Depends what you mean by "speed". Speed of execution, of course not. But speed of coding, sure. You could argue that it doesn't make a big difference in coding it, but I'd argue that using a for loop instead of this approach doesn't make a big difference (per iteration) either. It's all in how you use it.
|
|
|
|
|
I put each method call on a separate line for this very reason.
e.g.
someStuff
.Where(c => c != What)
.Select(d => d + The)
.Foreach(e => Hell(e));
What do you get when you cross a joke with a rhetorical question?
The metaphorical solid rear-end expulsions have impacted the metaphorical motorized bladed rotating air movement mechanism.
Do questions with multiple question marks annoy you???
|
|
|
|
|
Does that actually work for simplifying debugging now?
I haven't done any major LINQ work since VS2010; but then it would treat everything upto the semicolon as a single statement regardless of the newlining.
Debugging into it required replacing all the .'s with ;'` newlines and temp variables.
Did you ever see history portrayed as an old man with a wise brow and pulseless heart, waging all things in the balance of reason?
Is not rather the genius of history like an eternal, imploring maiden, full of fire, with a burning heart and flaming soul, humanly warm and humanly beautiful?
--Zachris Topelius
Training a telescope on one’s own belly button will only reveal lint. You like that? You go right on staring at it. I prefer looking at galaxies.
-- Sarah Hoyt
|
|
|
|
|
No, it doesn't help for debugging. I think it helps for readability, though. I keep the first one on the same line and then line up all the dots like so:
someStuff.Where(c => c != What)
.Select(d => d + The)
.Foreach(e => Hell(e));
|
|
|
|
|
For debugging, though, if you convert the lambda expression into a lambda statement, you can put a breakpoint in it. That can help in debugging. Usually what I end up doing is split the fluent chain into separate pieces if I need to debug it.
That being said, this is usually a style I employ as I'm finishing up code and have already tested it while doing my normal refactoring. (and when I know high performance is not necessary)
|
|
|
|
|
I just set breakpoints on the lambda expressions in the statements. The debugger is a little finicky on setting them there -- you have to click somewhere in the RHS of the lambda and then hit F9 to set the breakpoint. No harder to debug than any other bit of code.
I use Linq a lot, but for non-performant areas. I don't expect it to be faster to run, only faster to write, debug and maintain.
We can program with only 1's, but if all you've got are zeros, you've got nothing.
|
|
|
|
|
You can easily step into it using F11. You would see the deferred execution in action
|
|
|
|
|
He could have meant it was faster to write than do the foreach and the if statements. Not that it runs faster. And I find it is much faster to write.
|
|
|
|
|
No, he meant to execute. I set up some experimental code that looped many times using the various methods like native code and linq and timed them. I also pointed out that the linq code was using anonymous methods and that they had overhead too.
|
|
|
|
|
Writing all of your code in one big Main function is faster than any of this "object-oriented" nonsense.
And using C or assembly will be much faster than this JIT-compiled C# nonsense.
Of course, it will take a lot longer to write, and be much harder to debug. But premature optimization is much more important than sleep!
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
It's about trade-offs though. There is nothing wrong with going for a worse performing technology\method if you gain elsewhere and the gain is an acceptable trade. But using linq over a foreach gives no real gain in the kind of situations we're talking about, so for no gain you are suffering in performance.
|
|
|
|