Using IEnumerable nonsense for everything
-
harold aptroot wrote:
Is this style cancer?
Yes. Many fans of that style don't realize how many times the data gets copied and iterated when they do nonsense like that. What really irks me is the near-constant use of
ToList
orToArray
; those are definitely cries for help. Even a simpleforeach
should generally be avoided in situations where afor
will perform at least as well.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
-
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
-
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.
-
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! ;P
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
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)
-
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.
-
As others have said, it might give you "nerd points", but IMO it is the C# equivalent of APL one-liners - easy to write, impossible to debug or understand 6 months down the line. Under some circumstances, this coding style may produce faster code, but that remains to be measured.
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack. --Winston Churchill
Daniel Pfeffer wrote:
impossible to debug or understand 6 months down the line.
I'd have to disagree with that - I've got LINQ code going back eight years which is still perfectly understandable. It tends to be easier to read than the equivalent imperative code, especially if you try to squeeze all of the filtering, grouping, sorting and projecting code into one method to try to make it go faster.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
I promise you I'm not just flaming, I just really find those chained LINQy things hard to read. It's not like I haven't tried, I've been reading them for nearly a decade, I'm not getting used to them. It takes an extra step in my mind somehow, normal code I read and build up a picture of it in my mind, LINQy stuff I read, tear down, then build a picture. Clearly that is not the case for everyone here
Harold, is it easier on separate lines, or do you still find that difficult to read? (by the way, this is called "fluent syntax". I find when it's all on one line (except maybe calling .Single() or .First() or .ToList() at the end of something) it can be very difficult to read. But this I love:
someStuff.Where(c => c != What)
.Select(d => d + The)
.Foreach(e => Hell(e)); -
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
You can easily step into it using F11. You would see the deferred execution in action ;)
-
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! ;P
"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.
-
You've probably seen this style if you're done anything with C# after 2007 or so. someStuff.Where(c => c != What).Select(d => d + The).Foreach(e => Hell(e)); Instead of, you know, a plain old `for` loop with an `if` in it and so on. Or maybe `foreach` if you want to be fancy. So, now we have nearly a decade of experience with this, can we finally settle this question: Is this style cancer? I still think it is, and the retort "you just have to get used to it" isn't going to work any more. I file this firmly under "stupid one-liner 'clever' code with no benefits to compensate". Yes, I've argued in the past that "clever code" isn't necessarily bad, and I'll keep saying that - there's a time and a place for it. But not if you're just trying to be cute. "Oh look at me, I put everything on one line, +1 nerd points for me" And this is even worse. It's not just cute with no benefits to compensate, it's cute and harder to read. Side question, why is this style popular?
-
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.
F-ES Sitecore wrote:
using linq over a foreach gives no real gain
Except for more readable* and concise code. * For those of us who have been assimilated.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
F-ES Sitecore wrote:
using linq over a foreach gives no real gain
Except for more readable* and concise code. * For those of us who have been assimilated.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
That's a matter of opinion, in one of the articles posted on this thread MS explain why there is no ForEach for List and the reason being that it is less readable and offers no real advantage over the native foreach. You also forget "harder to debug" :)
-
It's literally a single "if" that's added into a loop. That's not enough to refactor out of it, anything it can be replaced by is at least as complicated. Writing an "except" method is certainly more complicated, and calling it isn't any simpler than what it replaces.
Linq is all about defining the query instead of the execution of the query. You say you can implement Except in a single line of code. Can you also do that for grouping, ordering, projection? And all those other possibilities, all used in combination? Using Ling you are sacrificing a little performance, and you are (read: should be) gaining a lot in maintenance. You can implement the above probably without problems. Can you also read the implementation of others without any problems? Using Linq you and your co-workers are all using the same methods, and therefor, can read each others code a lot easier, compared to a different implementation for you and every co-worker you have. Of course, you can completely kill the performance, and no-one will say that Linq is faster, and yes, you have to know what you are doing. But that is no different from all the 'other tools in your toolbox'.
-
That's a matter of opinion, in one of the articles posted on this thread MS explain why there is no ForEach for List and the reason being that it is less readable and offers no real advantage over the native foreach. You also forget "harder to debug" :)
As others have pointed out,
ForEach
is the odd man out here. Aforeach
loop of the results of the sequence returned from LINQ is the better option. But the bulk of LINQ is about telling the compiler what to do, not how to do it. And that makes the code much more readable (for some). Imagine you start with a big block of code in a single method. It takes a list, filters it, sorts it, groups it, filters it some more, projects it, and then processes it. You've got a fairly complex method which is specific to one task. If you need to repeat any of those operations, you have to duplicate the code. The first thing you would do is refactor the code, to move some of the common operations out into separate, simpler, reusable methods. You could then write simple unit tests for those methods, without having to set up the more complicated data for your original method, and without having to work out which part of the original method failed if the tests failed. Then, you would reuse those simpler methods elsewhere when you needed to do the same thing. Need to filter a list? CallSomeClass.FilterAList
. Need to group a list? CallSomeClass.MakeSomeGroups
. Pretty soon, you end up with a collection of utility methods that you're reusing everywhere. But the syntax is quite nasty:var source = GetAList();
var filtered = SomeClass.FilterAList(source, SomeFilter);
var sorted = SomeClass.MakeItSorted(filtered, SomeSortingCondition);
var grouped = SomeClass.MakeSomeGroups(sorted, SomeGroupingCondition);
var filteredAgain = SomeClass.FilterAList(grouped, AnotherFilter);
var result = SomeClass.ProjectAList(filteredAgain, SomeProjection);// Or:
var result = SomeClass.ProjectAList(
SomeClass.FilterAList(
SomeClass.MakeSomeGroups(
SomeClass.MakeItSorted(
SomeClass.FilterAList(
GetAList(),
SomeFilter),
SomeSortingCondition),
SomeGroupingCondition),
AnotherFilter),
SomeProjection);To tidy it up, you would like to be able to call each utility method as if it was defined on the
IEnumerable<T>
interface. You can't add the methods to the interface, since that would break everything that implemented it. So instead, you introduce extension methods, and the syntax becomes:var result = GetAList()
.FilterAList(SomeFilter)
.MakeItSorted(SomeSortingCond -
BillWoodruff wrote:
I get a glimpse of your shadow going around a corner
You are generous as always! There are some corners I probably should not be followed:
public static bool If(this bool b, Action action)
public static void IfElse(this bool b, Action ifTrue, Action ifFalse)
etc. Let's just call those "experiments." :) Marc
Imperative to Functional Programming Succinctly Contributors Wanted for Higher Order Programming Project! Learning to code with python is like learning to swim with those little arm floaties. It gives you undeserved confidence and will eventually drown you. - DangerBunny
Ha! But then there is value in experiments:
public static void ForEach<T>(this IEnumerable<T> sequence, Action<T, int> action)
{
// argument null checking omitted
var index = 0;
foreach(T item in sequence) {
action(item, index);
index++;
}
}For example, I am curious if I could find value in (probably with a different body implementation):
public static async Task ForEachAsync<T>(this IEnumerable<T> sequence, Func<T, Task> actionAsync)
{
// argument null checking omitted
foreach(T item in sequence) await actionAsync(item);
} -
Uhm, I thought you said any use of ToArray is a cry for help?
Regards, Nish
Website: www.voidnish.com Blog: voidnish.wordpress.com
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
-
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
onIEnumerable<T>
.Regards, Nish
Website: www.voidnish.com Blog: voidnish.wordpress.com
-
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! ;P
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
Richard Deeming wrote:
Writing all of your code in one big
Main
function is faster than any of this "object-oriented" nonsense.That is, almost certainly, not true. With one big function, the optimizer will have to practically shut-down. Many smaller functions can be highly optimized.
Richard Deeming wrote:
And using C or assembly will be much faster than this JIT-compiled C# nonsense.
Again, real world examples have shown that letting the computer do things like managing your resources, is much faster than trying to do it yourself manually.
Truth, James