𝄯 Sharp Regrets: Top 10 Worst C# Features



  • Indeed.

    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.


  • Banned

    @Maciejasjmj said:

    (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?


  • Banned

    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 ? ... : 
                       ...)) 
    {
       ... 
    } 
    

  • Java Dev

    Is that a variant on for/case paradigm? Don't you have array literals?



  • @PleegWat said:

    for/case paradigm

    That would require a switch on i, he's picking the collection to enumerate over based on some n.


  • Java Dev

    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.


  • Banned

    @Maciejasjmj said:

    Gah! Can't you just chain ternary operators?

    I hate ternary operators.



  • 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.


  • Banned

    That's what I ended up with - deep refactoring so my code will both compile and not look godawful.



  • @Maciejasjmj said:

    (new Action(() => {}))() I think does the job.

    @Gaska said:

    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.



  • @Gaska said:

    Readability is subjective.

    Only to you.

    @Gaska said:

    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.


  • Banned

    @Buddy said:

    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.


  • BINNED

    @Buddy said:

    [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.



  • @Gaska said:

    (()=>{})()

    What the fuck do you think this is - javascript?



  • @Gaska said:

    I hate ternary operators.

    You can give them all to me. I missed them so much in Nemerle that I built a macro version.



  • @tar said:

    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.


  • Discourse touched me in a no-no place

    @Maciejasjmj said:

    I've done some really dark and depraved stuff with lambdas

    :giggity:


  • Banned

    @Maciejasjmj said:

    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.

    @Buddy said:

    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 understanding foreach(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.

    @Bort said:

    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?

    @tar said:

    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.

    @tar said:

    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.



  • @Gaska said:

    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.


  • Banned

    @Buddy said:

    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.


  • Banned

    @Buddy said:

    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 result

    Both pages have about the same content, both are equally as well googlable and equally as useful for learning WTF is this keyword.

    @Buddy said:

    or 90% of the stuff that's in Haskell.

    Haskell is special. Don't mix it into this topic, please.


  • BINNED

    @Buddy said:

    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?

    @Buddy said:

    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.

    @Gaska said:

    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



  • @Gaska said:

    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.


  • :belt_onion:

    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.


  • Banned

    @HardwareGeek said:

    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’.



  • @Buddy said:

    The word you are looking for is ‘pretentious’.

    Just because a language's users are pretentious, that doesn't mean the language is.


  • Banned

    @Buddy said:

    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 I'm novice myself.

    FTFY


  • BINNED

    @Buddy said:

    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.


  • BINNED

    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.



  • @Buddy said:

    I'm already a better programmer than @Gaska, or any of the senior programmers at my work.

    Spoken like a true junior.


  • :belt_onion:

    @Buddy said:

    literally just born yesterday

    👶 🍼 ?


  • Discourse touched me in a no-no place

    @mrguyorama said:

    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. 😊



  • @antiquarian said:

    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.

    @antiquarian said:

    The idea is that at some point they grow up to become senior programmers

    Is that what happens, in your experience?


  • BINNED

    @Buddy said:

    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.

    @Buddy said:

    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.

    @Buddy said:

    Is that what happens, in your experience?

    Sometimes. The thing to remember, though, is that every senior programmer started out as a novice.


  • ♿ (Parody)

    @antiquarian said:

    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.


  • BINNED

    @Buddy said:

    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.


  • Discourse touched me in a no-no place

    @antiquarian said:

    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.


Log in to reply