• (nodebb)

    I especially like the "".Equals call, which is certainly valid, but inverted from how most people would think about doing the check. It echos Python's string join function, which is invoked on the join character (and not the string being joined), which makes me wonder if that's where this developer started out?

    It might be someone who believes that if ( 1 == x ) is actually necessary for, well, anything. Y'know, instead of if ( x == 1 ).

  • xorium (unregistered)

    "".Equals(Port) is a well known though ugly way to ensure that no nullpointer exception is thrown if Port is null. So it is very useful here where the developer has already checked that Port is not null.

  • Davide (unregistered)

    It is not "necessary" but in C/C++ and maybe other compiled languages the habit of writing "if (1 == x)" can make your life a lot easier, because if you mistype the == then you get a compiler error. Otherwise the small typo may result in a bug that's difficult to track down, because you end up executing an unwanted but valid branch with the problems manifesting themselves only at a later stage. It helped me when I was into C++, of yourse YMMV...

  • Black Mantha (unregistered)

    The reason to write "".equals(Port) instead of Port.equals("") throws an error when Port is NULL. So they probably saw the first syntax in some places and started using it. Apparently without really knowing why, because it makes the Port == null check superfluous. String.equals already does that check and returns false.

  • Black Mantha (unregistered)

    CORRECTION: Second half of my check was false. They wanted null to evaluate to true.

  • K (unregistered)

    Python's string join functionality is a method on the join value because it operates on any sequence of strings and not on "a string" as the article states. Sure, lists and tuples could have a "join" method, but so would all the other sequence types just in case. Also, what if the sequence is produced by a generator function? Where does the join method go then?

  • (nodebb)

    "".Equals(Port) could be a habit carried over from Java, where it's a common idiom for testing equality if the object reference can be null.

  • (nodebb)

    "".Equals(Port) irritates me. No need to run a string comparison, just do Port.Length = 0. (Yes, the compiler may optimise, but still.)

  • (nodebb)

    string.IsNullOrEmpty

  • randy (unregistered)

    I've seen if (Port==null || "".Equals(Port)) { /* do stuff */} a lot in JasperReports written for a Java application. I tend to agree with other respondents that about the null-safety of "".Equals(Port), but also how silly that order looks when executed after a null check. That said, I find that pattern really annoying because it means whatever it is in the report that uses that has the same behavior for null and an empty string, but not a blank string... And it makes even less sense when you consider that an empty string, if it were to "pass through," is literally nothing! What harm could it do?!

  • (nodebb)

    So much wrong with "".Equals() historically, it's mind-blowing. First it created a new string every single time which always has to get interned, then it calls a v-table call that did a lot of pointless type and nullability checks and finally you compared not against zero.

    Spoiler: In most architectures you want always to compare to zero (or null), because it is the most efficient way to do it. Hence the correct implementation of string.IsNullOrEmpty looks like this:

            public static bool IsNullOrEmpty([NotNullWhen(false)] string? value)
            {
                return value == null || value.Length == 0;
            }
    
  • (nodebb)

    It's possible that the StringValid function is old code. String.IsNullOrEmpty wasn't added until .Net 2.0.

  • mihi (unregistered)

    Python's join is fine. Ask a Python programmer what the remainder of dividing a string by a sequence is to be :)

  • (nodebb) in reply to K

    Python's string join functionality is a method on the join value because it operates on any sequence of strings and not on "a string" as the article states. Sure, lists and tuples could have a "join" method, but so would all the other sequence types just in case. Also, what if the sequence is produced by a generator function? Where does the join method go then?

    or of course they could have made it a function that took an iterable and a string, because python does actually support functions that take 2 arguments of different types.

  • Kotarak (unregistered)

    Python has so much weird design decisions. For example you can do something like this:

    def foo(someListyThing): yield from someListyThing

    This is basically equivalent to:

    def foo(someListyThing): for x in someListyThing: yield x

    However, you cannot do:

    async def foo(someListyThing): yield from someListyThing

    Why? I don't know. someListyThing might be a async generator? Then do something like async yield from like you do with for. I don't get it. And yes, manually translating it to the more verbose for loop works like a charm.

  • Tinkle (unregistered)

    You asked how it could get worse, I present this gem:

        const string NullString = "";
    
        public static bool StringValid(string? strToCheck)
        {
            return ((strToCheck ?? NullString).Equals(NullString)) ? false : true;
        }
    
  • (nodebb) in reply to Davide

    C/C++ and maybe other compiled languages the habit of writing if (1 == x) can make your life a lot easier, because if you mistype the == then you get a compiler error.

    For decades now, writing if (x = 1) in your C program causes the compiler to emit a warning. This is what Clang currently does:

    foo.c:7:8: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
        7 |         if (x = 1)
          |             ~~^~~
    foo.c:7:8: note: place parentheses around the assignment to silence this warning
        7 |         if (x = 1)
          |               ^  
          |             (    )
    foo.c:7:8: note: use '==' to turn this assignment into an equality comparison
        7 |         if (x = 1)
          |               ^
          |               ==
    1 warning generated.
    

    I cannot remember the last time I got caught out by that issue, perhaps in the late 1980's.

  • (nodebb)

    First it created a new string every single time which always has to get interned,

    Really "" isn't created just once as a string constant and interned by the C# compiler?

    Addendum 2025-09-26 07:46: s/Really/Really?/

  • (nodebb) in reply to jeremypnet

    Until .net 5 all string literals including "" were created from their binary representation and then interned (not by the compiler, that's handled by runtime). This was the only consistency .net had with strings until then, because pretty much everything when it came to strings was changed from release to release. Hence it was also bad practice not to use string.Empty instead. Recent version both the compiler and the runtime replace code using empty string literals both at code-gen and during (D)PGO including bad practices like using the virtual Equals method.

    Addendum 2025-09-26 08:56: I think even Stephen Toub was writing about it a long time ago in one of his .net performance posts but boy, finding that one is tough if you ever read one of those :-)

    Addendum 2025-09-26 09:02: Oh, BTW this is also the reason why you should use string interpolation in .net. It basically uses a ReadOnlySpan<char> of a char* instead of a string, so you don't have the interning overhead of literals because no string is ever created. But interpolations became only available after 5, I think 6 or 7, can't remember honestly.

  • (nodebb)

    I've said it before, and I'll say it again: strings were a mistake. We should just abolish them. No more text, everybody, we're done.

    But... But... But if we abolished strings, HOW would we be able to generate "creative" error messages?

  • Loren Pechtel (unregistered)

    Constant on the left is a standard safeguard in C for catching = used in place of ==. It shouldn't be considered a WTF, it just means C experience or learned from someone whose main language was C.

  • Officer Johnny Holzkopf (unregistered) in reply to Bananafish

    You mean something creative like "Oopsie! An error occured! Haha! Please try again later!" instead of 404?

  • Eric Riese (github)

    I hope I don't find my OptionalString class on here one day. It's a copy of the Java Optional class monomorphized for String but it treats null, empty and blank strings all as "empty".

  • Craig (unregistered) in reply to MaxiTB

    String interpolation has been around for a while. It's available in .NET Framework, not just the later Core-derived versions.

Leave a comment on “High Strung”

Log In or post as a guest

Replying to comment #684687:

« Return to Article