𝄯 Sharp Regrets: Top 10 Worst C# Features
-
Note that lambda expressions in themselves do not have a type because the common type system has no intrinsic concept of "lambda expression."
(new Action(() => {}))()
I think does the job. And that you can't do this follows from what was discussed above - C# (or CLR) doesn't like not to know what delegate type you're applying()
on.
-
(new Action(() => {}))() I think does the job.
Not if your lambda returns several lines of LINQ - because all the readability gains are immediately lost by giant cast to Func<>. Also, good luck at guessing which Func<>.
-
I don't see how you get any readability improvements by wrapping the whole thing in a self-calling lambda at all, though. If you're not planning to use it anywhere else, what benefit is there over, you know, just writing the body out in your method?
-
foreach (i in ()=>{select (n) { case 1: return ...; case 2: return ...; }}())
Basically, a hack around
select
not being expression.Readability is subjective.
-
Gah! Can't you just chain ternary operators?
foreach (var i in (n == 1? ... : n == 2 ? ... : ...)) { ... }
-
Is that a variant on for/case paradigm? Don't you have array literals?
-
for/case paradigm
That would require a switch on
i
, he's picking the collection to enumerate over based on somen
.
-
Still reads like he's taking a wrong approach. Possibly short a level of indirection - have one base function and a separate invoking function for each N that just passes in a collection (or some aggregate object) to the base.
-
-
You hate
select
in C# too.And ternaries are, in fact, the best tool for this job. Well, other than refactoring the whole code for sanity.
-
That's what I ended up with - deep refactoring so my code will both compile and not look godawful.
-
(new Action(() => {}))()
I think does the job.Not if your lambda returns several lines of LINQ - because all the readability gains are immediately lost by giant cast to Func<>. Also, good luck at guessing which Func<>.
Easily solved:
public static class Lambda { public static Func<TOut> Func<TOut>(Func<TOut> func) { return func; } public static Func<T1,TOut> Func<T1,TOut>(Func<T1,TOut> func) { return func; } //etc. public static Expression<Func<TOut>> Expr<TOut>(Expression<Func<TOut>> expr) { return expr; } public static Expression<Func<T1,TOut>> Expr<T1,TOut>(Expression<Func<T1,TOut>> expr) { return expr; } //etc. }
var func = Lambda.Func((int x, int y) => x + y); var expr = Lambda.Expr((int x, int y) => x + y);
And then chain on from there, if you need, using something like LinqKit's predicate builders.
-
Readability is subjective.
Only to you.
That's what I ended up with - deep refactoring so my code will both compile and not look godawful.
C# saves the day once again.
-
C# saves the day once again.
Have I mentioned the overall design of my application has become insane mess due to this? No? Then I mention it now.
-
[quote="Gaska, post:404, topic:50671"]
Readability is subjective.Only to you.
I disagree. The average Haskell program will be much more readable to an experienced Haskell programmer than to someone who just picked up a "Haskell for Dummies" (you'll know we're in the End Times if that title ever gets published) book and finished the first couple of chapters.
-
Then it's bad design. A bad craftsman blames his tools.
Normally I'd be with you on that, but I've done some really dark and depraved stuff with lambdas and even though I've ran into a few kinks here and there, having the whole application become a mess is still a sign that it's you, not C#, doing something seriously wrong here.
-
That's bad. When I write something, I want it to be immediately obvious to any reader exactly what I am saying. I don't want people to have to put on a smoking jacket and sit there puzzling through a hundred layers of abstraction when all they needed to get was the gist of it.
-
-
I hate ternary operators.
You can give them all to me. I missed them so much in Nemerle that I built a macro version.
-
You can give them all to me.
You can have some of mine, too. They seem to be inordinately popular among some Verilog developers; I've seen nested ternaries 20+ lines long. Shudder
-
Yeesh, don't get me wrong, I enjoy a good ternary as much as the next man, but damn, they are not to be nested!
return a ? b ? d : kill ? me : now : plz;
-
They tend to be used a lot in Verilog because they do simplify some things. You can write
wire x = expr;
rather than
wire x; always @(*) begin if (...) x = subexp_a; else x = subexp_b; end
(Both of these create threads that run any time a variable on the RHS of an assignment changes.)
They also eliminate a class of errors that can occur in code that is synthesized if static analysis can't prove that every possible path through the code results in an assignment to
x
. Still, they can be overdone.
-
I've done some really dark and depraved stuff with lambdas
-
Then it's bad design. A bad craftsman blames his tools.
You can't blame me for weird names of functions in million-line C project - there's just no way around it due to lack of namespaces. Similarly, you can't blame me for myriads of unnecessary utility functions used in only one place due to C#'s lambdas being fucked up.That's bad. When I write something, I want it to be immediately obvious to any reader exactly what I am saying.
It's impossible - someone who only ever seen C code will have a very hard time understandingforeach(var i in
, not to mention the other half of this line. You just can't write C# that will be immediately obvious to anyone. Same with any other language.What the fuck do you think this is - javascript?
Look. Even Java, the most godawful mainstream language, got lambdas right. And C# failed at it. WTF?You can give them all to me. I missed them so much in Nemerle that I built a macro version
The functionality is great, but the syntax is horrible. One of the most awesome features of Rust for me is that regular if-else is an expression - usable in all the same contexts where a+b is.Yeesh, don't get me wrong, I enjoy a good ternary as much as the next man, but damn, they are not to be nested!
return a ? b ? d : kill ? me : now : plz;
Bonus fun: PHP's ternary operator is right-associative.
-
someone who only ever seen C code will have a very hard time understanding foreach(var i in
Bull Shit. It's obvious what that does; it's right there in the name. But if they need to know the details,
c# foreach
is not hard to google, unlike java foreach syntax, or 90% of the stuff that's in Haskell.
-
It's obvious what that does
I've seen C people arguing that overriding methods in derived classes is too complicated! Never underestimate the stupidity of zealots.
-
But if they need to know the details, c# foreach is not hard to google, unlike java foreach syntax
Let's see.C#: googling c# foreach - first result
Java: googling java for - first resultBoth pages have about the same content, both are equally as well googlable and equally as useful for learning WTF is this keyword.
or 90% of the stuff that's in Haskell.
Haskell is special. Don't mix it into this topic, please.
-
When I write something, I want it to be immediately obvious to any reader exactly what I am saying.
I think we may be talking past each other here. Do you mean any reader at all, or any reader who understands the language you're using?
Bull Shit. It's obvious what that does; it's right there in the name. But if they need to know the details, c# foreach is not hard to google, unlike java foreach syntax, or 90% of the stuff that's in Haskell.
Never mind. If you want COBOL you know where to find it.
Haskell is special. Don't mix it into this topic, please.
Agreed. I was just trying to provide an example and @buddy had a knee-jerk reaction to the word "Haskell". Any programming language would have done for my point.
-
We JUST upgraded our application to Java 1.7 for this release. It broke things. Dear God
-
Haskell is special.
Discourse is special. The kid drooling in the corner is special. Haskell is special.
Haskell may or may not be special in that way (I don't know; all I know about it is the occasional snippet I read here), but be careful using that adjective around here because that's what people are likely to think.
-
At least it's on 1.7
That's a plus.
-
If you had java 1.8 installed, our application would not run. Something internally would crap itself in some weird manner and the entire application would not boot up.
Also, it feels dirty that "uncheck stop execution on uncaught exception" is in the developer onboarding guide, which also hasn't been updated for 3 years. That in itself was fun.
-
Haskell may or may not be special in that way
It's not. It's special in exactly opposite way. Kinda like communism and nazism.
-
I don't want it to be understandable by advanced users but not novices. Because if what I've seen so far is any indication, it's gonna be novices that are maintaining my code, while the senior programmers are off building cloud castles that nobody wants and nobody needs.
-
The word you are looking for is ‘pretentious’.
-
The word you are looking for is ‘pretentious’.
Just because a language's users are pretentious, that doesn't mean the language is.
-
I don't want it to be understandable by advanced users but not novices. Because
if what I've seen so far is any indication, it's gonna be novices that are maintaining my code, while the senior programmers are off building cloud castles that nobody wants and nobody needsI'm novice myself.
FTFY
-
I don't want it to be understandable by advanced users but not novices. Because if what I've seen so far is any indication, it's gonna be novices that are maintaining my code, while the senior programmers are off building cloud castles that nobody wants and nobody needs.
Are you planning on swapping out the novices every so often when they become familiar with the language so that you always have novices working on your code? Being a novice is supposed to be temporary, while the changes to your code to permit it to be understood by someone who hasn't finished the "Language X for Dummies" book are permanent.
It also sounds like you need better senior programmers.
-
The whole god damn world needs better senior programmers. Where are they to be found? I was literally just born yesterday and I'm already a better programmer than @Gaska, or any of the senior programmers at my work.
-
That's where your novices come in. The idea is that at some point they grow up to become senior programmers.
On the other hand, if you think you're a better programmer than everyone else, then maybe TRWTF is you.
ETA: By the way, the part about novice programmers becoming senior programmers down the road only happens if you don't restrict your code to features that can be understood by novices.
-
I'm already a better programmer than @Gaska, or any of the senior programmers at my work.
Spoken like a true junior.
-
-
We JUST upgraded our application to Java 1.7 for this release. It broke things.
There are some evil tricks to going from 1.6 to 1.7. In particular, there are subtle changes to how SSL support works that fucked over our software, and I was hit badly by changes to the bytecode format (though I could fix those by upgrading some of the libraries I was using; a nightmare, but just a small one).
I've been too busy hunting stupid hardware problems and dealing with users to worry about what breaks when going to 1.8 yet.
-
ETA: By the way, the part about novice programmers becoming senior programmers down the road only happens if you don't restrict your code to features that can be understood by novices
Knowledge of language features is a shitty proxy for programming skill. You know what does make a good programmer? Discipline. Things like requirements gathering, testing, checking your code in to the repo, automating mundane tasks instead of adding manual steps to the build process all willy-nilly. Things that are all but unheard of to our senior devs.
Tony taught me this, back when I was trying to be a chef. He asked me “what makes a good meal?” I was young and dumb, so I start spouting off a bunch of pretentious shit about ‘flavors’ and ‘balance’ and god knows what else before he cut me off. “No, what makes a good meal is that it tastes delicious. Every component of every dish must taste delicious. You can't make a good meal out of bad ingredients. Until every single thing you cook tastes delicious, there's no point worrying about anything else.”
When I see people using language features for the sake of using language features, it just makes me feel like they've lost sight of what's actually good about their code. Like, we're not being paid to write code, we're being paid to produce results.
The idea is that at some point they grow up to become senior programmers
Is that what happens, in your experience?
-
Knowledge of language features is a shitty proxy for programming skill.
Your senior programmers would be just as bad if they didn't have the knowledge of language features, based on what you've told me about them. You can do plenty of bikeshedding using only basic language features.
Actually, I disagree with @bort on one point. You strike me more as a proud anti-intellectual than a novice.
Tony taught me this, back when I was trying to be a chef. He asked me “what makes a good meal?” I was young and dumb, so I start spouting off a bunch of pretentious shit about ‘flavors’ and ‘balance’ and god knows what else before he cut me off. “No, what makes a good meal is that it tastes delicious. Every component of every dish must taste delicious. You can't make a good meal out of bad ingredients. Until every single thing you cook tastes delicious, there's no point worrying about anything else.”
OK, you're the new chef, but you can only use salt, pepper and oregano.
Is that what happens, in your experience?
Sometimes. The thing to remember, though, is that every senior programmer started out as a novice.
-
OK, you're the new chef, but you can only use salt, pepper and oregano.
Oregano roast for dinner! /DF
Filed Under: INB4 BENL
-
Of the two, I far prefer the one that sticks to mostly basic language features. If I need to use some part of his code, I just need to ask myself “how would I have handled this”, or I can just ask him. The other one seems to have a habit of writing over-architected code that still manages to contain, for example, string concatenation of html, and then abandoning it, presumably because it became too fragile and complicated even for him.
-
The other one seems to have a habit of writing over-architected code that still manages to contain, for example, string concatenation of html, and then abandoning it, presumably because it became too fragile and complicated even for him.
So, you're admitting that the problem isn't using advanced language features?
You can overarchitect in COBOL. I've seen it done.
-
That's true. But I'm still not giving up on my anti-intellectual ways.
-
a proud anti-intellectual
It should be remembered that the very best comes when you combine intellectual learning with good grounded practice. Just focusing on the intellectual side leaves you inclined to wander off into architecture astronautics and ivory-tower flights-of-fancy. Yet without it, a practitioner will tend to focus on the wrong aspects and end up stuck in a rut: they might be very fast at what they do in that rut, but they still get their faces trodden into the mud frequently.
A lot of people aren't really ready for advanced learning at 18 or 21. A lot of teaching of advanced learning is bloody awful. These facts do not detract from my point.