Using IEnumerable nonsense for everything
-
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 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.
Read my (free) ebook Object-Oriented Programming in C# Succinctly. Visit my blog at Sander's bits - Writing the code you need. Or read my articles here on CodeProject.
Simplicity is prerequisite for reliability. — Edsger W. Dijkstra
Regards, Sander
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.
Check out my blog at http://msdev.pro/
-
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.
Check out my blog at http://msdev.pro/
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 :)
Read my (free) ebook Object-Oriented Programming in C# Succinctly. Visit my blog at Sander's bits - Writing the code you need. Or read my articles here on CodeProject.
Simplicity is prerequisite for reliability. — Edsger W. Dijkstra
Regards, Sander
-
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?
-
OriginalGriff wrote:
Would you like to write and debug "Except" each time you need it?
Actually yes, so I wouldn't end up in that situation of horribly nested function calls in your second code block.
-
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.
-
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…
-
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 tmpStuffList = new List();
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. ;)
-
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.
-
I use it - though not the .ForEach on the end - because there are times when it provides a reliable, succinct, and clear way to process list (or other collection) based data.
var vidsWithOutPics = vidList.Except(vidsWithPics).Where(v => !v.IsAlternateTitle);
Or
var inDuration = DiskFile.GetAll().Where(df => !df.HasDuration).Select(df => df.Video).Distinct();
Or
var noSizeList = videoFiles.Where(file => file.Bytes < 0 && files.Contains(file.Location));
All I'm doing is "hiding" the loop so I don't have to write it! Yes, I could write each of those as loops - they aren't at all complex - but they would be longer; they would need debugging each time I wrote them. The other alternative would be to use Linq syntax, and that's pretty horrible!
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
Linq => Backward SQL
We're philosophical about power outages here. A.C. come, A.C. go.
-
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.
this thread only shows that you're hellbent on your "One true way" of coding, so there's not much to discuss here. but do keep in mind that calling a style "cancer" just because you don't want to learn how to read and use it is exactly what causes so many flamewars on the IT world (tabs vs spaces anyone?). Sure, you tell me it's just an
if
but you know what? I much prefer to readsomeList.Where(condition).Select(fields).Distinct().OrderBy(field)
than the alternative
HashSet distinctSet = new HashSet();
foreach(var item in someList){
if(condition){
distinctSet.Add(item);
}
}specially if you want to roll your own sorting method at the end. As a last note, i sometimes work with code where the order of operations (where, distinct, etc) sometimes yields different results and is important (due to crazy business rules, what can you do), so it's way easier to get the intent from the link way, but I recognize that you mileage may vary on that last one.
-
this thread only shows that you're hellbent on your "One true way" of coding, so there's not much to discuss here. but do keep in mind that calling a style "cancer" just because you don't want to learn how to read and use it is exactly what causes so many flamewars on the IT world (tabs vs spaces anyone?). Sure, you tell me it's just an
if
but you know what? I much prefer to readsomeList.Where(condition).Select(fields).Distinct().OrderBy(field)
than the alternative
HashSet distinctSet = new HashSet();
foreach(var item in someList){
if(condition){
distinctSet.Add(item);
}
}specially if you want to roll your own sorting method at the end. As a last note, i sometimes work with code where the order of operations (where, distinct, etc) sometimes yields different results and is important (due to crazy business rules, what can you do), so it's way easier to get the intent from the link way, but I recognize that you mileage may vary on that last one.
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
-
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?
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".
-
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
It was hard for me too, but once you understand how the context shifts it becomes way easier. LINQ queries have a different flow from the rest of the imperative code and are best left a little separated from stuff like for loops and complex conditionals, they require you to use the same way of thinking you use when writing SQL. It's not that you are telling the machine what to do, you're telling it what you want done, so you read this:
someList.Where(condition).Select(field)
As "Give me
field
for all objects wherecondition
is true" instead of "For each object, if condition is true, stuff field on another list". Truth is, those kind of LINQ queries are just convenience. The real power of LINQ comes when you start using joins and groups, like this example from LINQPad (still on the simple side):var query =
from o in Orders
group o by o.ShipCountry into countryGroups
select new
{
Country = countryGroups.Key,
Cities =
from cg in countryGroups
group cg.ShipPostalCode by cg.ShipCity into cityGroups
select new
{
City = cityGroups.Key,
PostCodes = cityGroups.Distinct()
}
};that produces this output:
// Brazil
// Campinas
// 04876-786
// Resende
// 08737-363
// Rio de Janeiro
// 02389-673
// 02389-890
// 05454-876As much as I can write that using for loops and conditionas, i don't want to write it that way. Also, join's and group's are the only thing I'll ever use query syntax for, they are somewhat easier to understand that way.
-
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.
-
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, 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
-
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.