C# hate



  • @lucas said:

    Underscores for private variables is actually a no-no

    Everything your link points to which supports your argument is based on opinion. Where I work, underscores for private variables is the standard, and from the answers to that SO question, it is very common. There is absolutely nothing in the C# which prevents the use of an underscore in a variable name.


  • Discourse touched me in a no-no place

    @Jaime said:

    If you want a rational argument for why the stack trace should start at "throw"...

    But you've not presented a rational argument. You've presented code that is very much not the normal case for exceptions, which is straight:

    if (a) throw new Exception();
    if (b) throw new Exception();
    

    We can beat around the bush all you want, but that's definitely the most common case by far. Putting the stack trace construction inside the constructor makes the Exception class significantly less special than it would be otherwise.

    Don't think I'm convincing you though. ;-)



  • @lucas said:

    Underscores for private variables is actually a no-no

    More evidence that Microsoft doesn't have a problem with it...

    The CLR naming conventions are designed to be for all CLR languages, not just for C#. The other popular CLR language actually creates underscore prefixed locals for you. This is valid VB.Net:

    Public Property X As Integer
    
    Sub y()
        _X = 12
    End Sub


  • @dkf said:

    But you've not presented a rational argument. You've presented code that is very much not the normal case for exceptions, which is straight:

    That's simply a degenerate case. If you "throw new", then it doesn't matter which of the two anchors that stack trace. Any discussion about which is correct must use examples where "new" comes before "throw".



  • Yes, _ variables were The One True Way at least back when I did VB.NET. VB is not case sensitive so underscores were the preferred way to distinguish public properties from their private backing variables.



  • Variant arrays. Lack of higher-order types. Unsealed classes by default. Generic classes cannot be variant. "protected internal". Collection initialization syntax that requires mutable collection types.

    If you want to extend this to the .NET libraries, there are many more. :)



  • @mott555 said:

    Yes, _ variables were The One True Way at least back when I did VB.NET. VB is not case sensitive so underscores were the preferred way to distinguish public properties from their private backing variables.

    It's been a while since I used VB, but doesn't option explicit force case sensitivity?



  • @StephenCleary said:

    Variant arrays. Lack of higher-order types. Unsealed classes by default. Generic classes cannot be variant. "protected internal". Collection initialization syntax that requires mutable collection types.

    💏

    Also, Everything has to be in a class. Built-in default(), the existence of which prevents null from being purged (long story). Lack of syntax transforms, which would allow many of the desired features (i.e. public T Prop { get; notify; } ) to be implemented. Single-dispatch. Poor support for OOP.



  • @abarker said:

    It's been a while since I used VB, but doesn't option explicit force case sensitivity?

    I don't know what option explicit even means.

    At the time I was a student employee working on other developer's code, so I'm sure there was a lot to VB.NET that I never saw or understood.



  • @abarker said:

    It's been a while since I used VB, but doesn't option explicit force case sensitivity?

    Nope. VB.Net isn't intended to be case-sensitive - you won't find a statement or compiler option to make it so.



  • @Jaime said:

    That's simply a degenerate case. If you "throw new", then it doesn't matter which of the two anchors that stack trace. Any discussion about which is correct must use examples where "new" comes before "throw".

    Ok, so you expand @dkf's example to this:

    if (a)
    {
    Exception aEx = new Exception();
    throw aEX;
    }
    if (b)
    {
    Exception bEx = new Exception();
    throw bEX;
    }
    

    Really, there's only one argument I can think of that makes sense for setting the call stack at throw instead of in the constructor: to allow for setting properties. Except that doesn't even work. Every Exception class I've used only has public get on the properties. The set is almost always private (sometimes protected). This forces you to set the properties as part of the constructor, so there's no reason to do anything between the construction and throwing of the exception. And there is every chance that by putting code between the constructor and the throw, you may be omitting valuable information from the exception.



  • @mott555 said:

    I don't know what option explicit even means.

    @Jaime said:

    Nope. VB.Net isn't intended to be case-sensitive - you won't find a statement or compiler option to make it so.

    Ah sorry, just checked. I was misremembering anyway. option explicit was for requiring you to declare a variable before using it.



  • Those are all just coding convention that have resulted from the decision to create a stack trace on "new". Any code that has problems will always look like bad practice, because the accepted practices were built so that you don't get bitten by this behavior.

    So, stop mentioning that code that has a problem is bad code - that's beside the point. It's also irrelevant if you can re-write code in a way that hides the behavior. The mere fact that it's valid to write code that creates a hard-to-debug stack trace is evidence that the stack trace isn't being built with the proper information.



  • @Maciejasjmj said:

    (it's similar enough to make you feel comfortable with just writing things as if they were SQL, then suddenly throws you off - like, why does select go at the end?)

    Because that's the only place that it makes sense to put it, and the people who designed SQL made a seriously boneheaded move with that.

    In any other case, when data is organized in a series of values of different levels of specific-ness, it always starts from most specific and proceeds to most general, or starts from most general and proceeds to most specific.

    For example: phone numbers go [country code] [area code] [local region] [individual suffix]. Most general to most specific.
    Street addresses go [addressee] [number] [street] [city] [state] [country]. Most specific to most general. (The ZIP code is an anomaly, a special optimization introduced to make post office routing easier, but even it is organized: most general to most specific. Just about anywhere on the West Coast starts with a 9, for example.)

    I could name plenty of other examples, but the pattern shows up everywhere. Even in other SQL commands such as INSERT and UPDATE. But for whatever reason, for SELECT, they threw common sense out the window and started with most specific (set of fields), then most general (set of tables), then the intermediaries. It may not seem like such a big deal on a trivial SQL query, but just try reading a query that contains multiple nested sub-selects. It's horrendously difficult to parse because there's no easy way to locate the FROM for each distinct subquery.

    No, this is one of the things LINQ syntax got 100% right. I just wish IBM had gotten it right for SQL.



  • @Mason_Wheeler said:

    No, this is one of the things LINQ syntax got 100% right. I just wish IBM had gotten it right for SQL.

    I love explaining to people learning SQL that table aliases defined in the FROM clause work in the SELECT clause. You really can't write a non-trivial SELECT statement in the order you read it.



  • @Jaime said:

    Those are all just coding convention that have resulted from the decision to create a stack trace on "new".

    No, they aren't. Let's take a look:

    @abarker said:

    Every Exception class I've used only has public get on the properties. The set is almost always private (sometimes protected).

    This has more to do with preventing the exception handler from changing the properties than when the stack trace is created. Can you imagine the problems that would arise if an exception handler could change the properties of an exception? One bad line of code, and you'd be screwed.

    @abarker said:

    This forces you to set the properties as part of the constructor, so there's no reason to do anything between the construction and throwing of the exception.

    Ok, so once the exception is constructed, we can't change any of the properties. Well shit, guess there's no point in creating the exception object until it's needed. Creating it ahead of time just robs us of the chance to add in valuable debugging information. Best to create the exception when the exception conditions are encountered so that all the available information can be included. Well, at that point, there's nothing else to be done, except throw the exception.



  • So.... why not create the stack trace at "throw", since - from your description - it will always be the same location as the "new"?

    Do we spend more time debugging code written by competent professionals, or code written by people who have no idea what they are doing? The difference between a good language and a bad language is how is behaves under duress, not how it behaves when people are using it "by the book".



  • Microsoft internal guidelines linked in the stackoverflow link say differently (I should have just referenced it directly) ... TBH I don't care either way, but I was pointing out that the underscore notation isn't recommended.



  • @Jaime said:

    So.... why not create the stack trace at "throw", since - from your description - it will always be the same location as the "new"?

    I would assume that's extra work for the compiler when setting it up inside the exception constructor would Just Work.



  • @abarker said:

    Can you imagine the problems that would arise if an exception handler could change the properties of an exception?

    What's stopping someone from defining an exception class with public setters? That's just convention. This situation is real and there's nothing you can do to prevent it. If a language were to define a syntax that makes exception instances immutable after being thrown, I would applaud the feature. Neither Java not C# have this feature, but their communities do accept it as a convention.



  • @mott555 said:

    I would assume that's extra work for the compiler when setting it up inside the exception constructor would Just Work.

    Limiting language features to make compiler implementation a bit easier results in a worse language. e.g.: Java and exceptions.



  • @lucas said:

    Microsoft internal guidelines linked in the stackoverflow link say differently (I should have just referenced it directly) ... TBH I don't care either way, but I was pointing out that the underscore notation isn't recommended.

    Microsoft's internal standard has nothing to do with how they expect everyone else to use it.



  • Why would they be any different?



  • @lucas said:

    Why would they be any different?

    If they expected people to avoid underscore prefixes, they could have done something to make it unusable. Besides it's their Internal Standards, not their Recommended Practices.



  • Their internal standards and recommended practices are the same for everything that is important, if someone followed the internal standards as opposed to the recommened practices, I doubt anyone would notice the difference in the real world.

    Also it is false to claim that is unusable without the syntax, for a start private attributes should be camelCase and not PascalCase. You can always use the this keyword in your code if you really wanted to press the point.

    TBH I don't care either way.



  • @Jaime said:

    What's stopping someone from defining an exception class with public setters?

    Well, if you derive from System.Exception, you can't make setters on the "interesting" properties public (unless you maybe really go out of your way...).

    Anyway, a pointless discussion, since not constructing the exception object right where it's thrown is verging somewhere between sabotage and idiocy. I can honestly see no case in which I would want to do that - unless maybe your exception constructor has side effects? But then it's idiocy anyway.



  • Not even this example of exception-oriented programming has exceptions created anywhere other than the place they're thrown.



  • @Maciejasjmj said:

    Anyway, a pointless discussion, since not constructing the exception object right where it's thrown is verging somewhere between sabotage and idiocy.

    I concede...
    No developer is stupid enough to ever do this and there will never be a web site devoted to collecting stories about their massive stupidity.



  • @lucas said:

    Also it is false to claim that is unusable without the syntax

    Good thing I didn't claim it is unusable. I claimed that they could make it unusable.



  • Setting the stack of an exception when it's thrown is another example of C# allowing its power to shoot yourself in the foot. Not a Bad Idea™, but definitely a potential for abuse.

    Arguing about naming things with camelCase or ProperCase means that you need to be slapped around with a trout for a bit.

    I'm not sure whether LINQ should be in the Bad Ideas Thread, or the Evil Ideas Thread.



  • I have an ex-C# hate.

    I've just re-started writing Windows apps and am incredibly happy that so far all the things that were missing from 8's API have been added to 8.1's and all those dirty hacks (which I truly hated) are no longer needed.

    Plus, universal apps is a very good thing \o/


  • Discourse touched me in a no-no place

    @Maciejasjmj said:

    Anyway, a pointless discussion, since not constructing the exception object right where it's thrown is verging somewhere between sabotage and idiocy. I can honestly see no case in which I would want to do that - unless maybe your exception constructor has side effects? But then it's idiocy anyway.

    I think I once saw a somewhat valid reason for doing it (throwing an exception in code that had to be extremely fast? or maybe where the code was expected to be throwing in a low-memory situation? I forget which) but frankly I'd generally consider it to be a code stench, a place where someone's lost the plot thoroughly. Having an exception allocated “just in case” is plain silly because that just encourages using the exception twice (dumb idea!) possibly from different threads (astoundingly dumb!) and the cost of allocation should never be taken as a reason to not throw…



  • @dkf said:

    I think I once saw a somewhat valid reason for doing it (throwing an exception in code that had to be extremely fast? or maybe where the code was expected to be throwing in a low-memory situation? I forget which)

    I don't think either makes any sense. If you're in a low-memory situation, you can't get any better than defering the creation to the last possible moment - that is, right as you throw. Unless you want to fail with OOM as fast as possible, maybe...

    If you're in a speed-critical section, you shouldn't really be using exceptions in the first place. They're not as slow as people make them out to be, from what I know, but I guess you could save some cycles by wrapping it up so that the outer code throws.



  • Better question to go against the argument: why the fuck are you throwing a generic Exception.


  • Discourse touched me in a no-no place

    Usually it's more specific than that, such as wanting to handle all IO-related exceptions except those relating to end-of-file, which you want to propagate to the caller (which it is meaningful for).


  • Discourse touched me in a no-no place

    My google-fu is defeated. The best argument I've actually found so far is some sort of exception factory where the exact exception class isn't really known at the point where the caller throws (because neither Java nor C# can do much about directly overriding how new chooses which class to instantiate).

    I'm not really all that convinced by it either.



  • Are you guys still trying to make sense of code that was submitted as "Debugging this mistake would be difficult due to language behavior"? Even worse is JazzyJosh commenting that the submitted bad code uses the wrong Exception class when any code that throws an exception can be used as an example of Java's stupidity. That's about the worst case of "can't see the forest for the trees" that I've seen in a long time. Do I live in a different world from you guys or is code that's being debugged not, by definition, incorrect?

    How could "That code isn't written to standards or sanity" be a valid defense for "the debugging facilities of this language are screwy".


  • Discourse touched me in a no-no place

    @lucas said:

    Underscores for private variables is actually a no-no

    And that's only because it's not legal[1] C, because leading _ is reserved for libraries or system code, I forget which.

    [1] legal may not be the word I want. The compiler will let you do it, unless you choose a variable name that's already taken. A lot of internal implementations of the CRT will have functions and variables with leading _. For that matter, if you look at MS' CRT, a lot of public library functions have leading _.

    ETA: Awesome job turning half of my underscores into underlining! Discurse strikes again!



  • Just writing this before I read the rest of the post. While I agree the example in OP should be written with the extension method rather than LINQ syntax, thanks to the syntax you can do some pretty cool and involved stuff.

    Like, for example, a ray-tracer

    Yes, the ray-tracer written in pure C# (see linqlink in the blog post) looks much saner

    Filed under: Candidate for the Bad Ideas Thread



  • Love the await/async stuff that's been added too



  • Relevant for those posts at the start of the thread (before the debate about throw), Microsoft has a uservoice page for C# where you can request and vote for features etc. With the WP, Xbox and Cortana uservoice pages, the features usually get put into the very next release, so if you want something fixed, improved or added, go and post and vote for it there.

    TCoDICK could learn a thing or two from it



  • Well you can rewrite the whole thing using extension methods. And if you did, you'd see what's going on. Each innocent looking let a = expression(b) is creating a new throwaway object with added properties. Not the most efficient thing ever.



  • @Spencer said:

    Relevant for those posts at the start of the thread (before the debate about throw), Microsoft has a uservoice page for C# where you can request and vote for features etc. With the WP, Xbox and Cortana uservoice pages, the features usually get put into the very next release, so if you want something fixed, improved or added, go and post and vote for it there.

    TCoDICK could learn a thing or two from it

    Didn't know about the uservoice site.

    The most upvoted request right now: Debug Lambda expressions

    Yes! YES! How annoying is you have no way of digging into a more complicated expression tree? I remember actually splitting the thing into chunks (var phase1 = ...; var phase2 = phase1.Select(...) just so I could figure out what's breaking. This deserves to be on the master list. Luckily, seems like they are on it.

    The second on the list (with order of magnitude less votes to boot): Add non-nullable reference types in C#
    Ok, looks useful. But not a big peeve of mine.

    The third: Update standalone FxCop to support .NET 4.5 and Portable Libraries
    I have no idea what this is.

    The fourth: Expand Generic Constraints for constructors

    public void DoSomething<T>() where T : new(string, int) { /* do something */ }

    Ok, this seems unworkable IMO.

    And so on. The first one is the best.



  • @Mason_Wheeler said:

    Because that's the only place that it makes sense to put it, and the people who designed SQL made a seriously boneheaded move with that.

    Mathematical notation:
    { f(x) | x ∈ ℝ, p(x) }
    Haskell:
    [ f x | x <- L, p x ]
    Python:
    ( f(x) for x in L if p(x) )
    SQL:
    select f(x) from t where p(x)
    LINQ:
    from x in L where p(x) select f(x)

    SQL just followed the suit here, LINQ is the odd man out. And it was not a new suit, mind you. The mathematical notation has been around for more than a century when SQL was created.

    Also in my experience the selected items are the most important bit that should be stated first, because when you write the follow-up code that processes the query you only need to refer to the column list and not the other parts.

    @Mason_Wheeler said:

    Even in other SQL commands such as INSERT and UPDATE.

    Really? UPDATE states the table (least specific) first, the columns to update (most specific) second and condition (intermediate) last. But in a sense the columns to set are again more important. I won't really deal with INSERT; non-trivial INSERT is just a prefix for SELECT.

    @Mason_Wheeler said:

    It's horrendously difficult to parse because there's no easy way to locate the FROM for each distinct subquery.

    The first thing I look for in a subquery is what it returns. And thankfully that is right there at the beginning. And then where it comes from and that is next. Exactly as it should be.


  • ♿ (Parody)

    @Bulb said:

    Also in my experience the selected items are the most important bit that should be stated first, because when you write the follow-up code that processes the query you only need to refer to the column list and not the other parts.

    @Bulb said:

    The first thing I look for in a subquery is what it returns. And thankfully that is right there at the beginning. And then where it comes from and that is next. Exactly as it should be.

    These.


  • FoxDev

    @cartman82 said:

    Well you can rewrite the whole thing using extension methods.

    Why do that when the compiler does it for you? 😛
    Plus the LINQ syntax looks cleaner for anything non-trivial.
    @cartman82 said:
    Each innocent looking let a = expression(b) is creating a new throwaway object with added properties.

    Does it though? It depends more on how those clauses are translated into the extension method syntax.



  • @RaceProUK said:

    Why do that when the compiler does it for you? Plus the LINQ syntax looks cleaner for anything non-trivial.

    Not according to my sense of taste, which is objectively superior.

    @RaceProUK said:

    Does it though? It depends more on how those clauses are translated into the extension method syntax.

    Pretty sure let is always translated into an anonymous object. Maybe the compiler is smart enough to group multiple lets into one object. Either way, his point was "you can do this with LINQ that you cannot with extensions".


  • FoxDev

    @cartman82 said:

    "you can do this with LINQ that you cannot with extensions"

    Which is of course total bollocks, since the first thing the compiler does with the query comprehension syntax is translate it into extension method syntax 😃



  • To this untrained eye, not knowing what if threw the exception exactly is what the code says and throw silently changing the exception object is TRWTF.

    First you construct an exception without parameters, and it is reasonable for the default constructor to ask the reflection subsystem, "hey, can you give me the current stacktrace? kthx". Then you throw the exception in one case or the other, but it's not clear at all that the throw command should change the exception object I've already constructed.

    Whatever happened to the principle of least surprise?

    Uh, Python actually does the same as C# and the traceback starts from where raise is called, and not where the Exception is created. That appears to be the case because the error stacktrace is not an attribute of the exception object in the first place.



  • I always wanted better syntax for a construcor that just sets a number of properties. i.e. how often do you do this

    class Rectangle{
        public int PositionX {get;set;} // repeat me for PositionY, Width, Height....
    
        public Rectangle(int x, int y, int width, int height){
            PositionX = x;
            PositionY = y;
            Width = width;
            Height = height;
        }
    }
    

    Would prefer some constructor like:

    public Rectangle(prop PositionX, prop PositionY, prop Width, prop Height){
    }
    

    Where the prop keyword lets you know that the parameter in question maps directly to a property of the same name.


Log in to reply