His Own Way to Newline

« Return to Article
  • Hans 2008-02-15 08:07
    Honestly, I want one of those jobs where you get paid for each line of code as well... :-(

  • ParkinT 2008-02-15 08:07
    "//The way everyone does it."

    Yeah, there's a reason EVERYONE DOES IT this way.

    I love it!
  • ObiWayneKenobi 2008-02-15 08:18
    ParkinT:
    "//The way everyone does it."

    Yeah, there's a reason EVERYONE DOES IT this way.

    I love it!


    And it's called "being lazy". Same reason why people who use VB.NET (no, that's not the real WTF) use the VB6-lookalike shortcut functions instead of the language-agnostic .NET Runtime version (Left() and Right() instead of Substring, for example, or Len(Foo) instead of Foo.Length).
  • Drum D. 2008-02-15 08:19
    "//The way everyone does it."

    1. Clean
    2. Easy to write
    3. Easy to read
    4. Easy to teach
    5. Easy to learn
    6. Easy to remember
    7. Elegant
    8. Available in most of the up-to-date programming languages
    ... (please feel free to continue the list)
  • joe.edwards 2008-02-15 08:20
    On Windows platforms, "\r\n" == Environment.NewLine. If you know the only platform your software will run on is Windows (e.g. server-side code), then there's no real distinction.
  • snoofle 2008-02-15 08:31
    But... but... but what if someday someone comes up with a new way of implying "cr-lf"? You absolutely MUST write encapsulated code in case this happens!

    Someone once actually told me not to use literal field specifiers (eg: "%d") in calls to printf in case some day they change the syntax. Right. It's only been unchanged since 1970, and a change like that would only break, oh, almost every program ever written.
  • A Nonny Mouse 2008-02-15 08:32
    when a vb developer meets .net, coming through the rye..
  • Carra 2008-02-15 08:34
    The real WTF is not using a StringBuilder!
  • sobani 2008-02-15 08:34
    Windows has:
    "\r\n"

    Linux has:
    "\n"

    MacOS has:
    "\r"

    That's why you should use the Right Way instead of the Easy Way.
  • AbbydonKrafts 2008-02-15 08:37
    The way "everyone does it" is technically wrong. As Joe Edwards pointed out, "\r\n" is the Windows new line. There is a reason for "Environment.NewLine". It allows porting between the frameworks (such as Mono). It will output the new line based on the host OS.

    Since the majority of .NET developers are probably developing for Windows, "\r\n" should be used; otherwise, stick with "the right way" of Environment.NewLine.
  • mfah 2008-02-15 08:38
    At the very least I want to see a NewLineProvider. Plus it's not culture-neutral.
  • John 2008-02-15 08:42
    No

    myString = string.Format("Line1{0}Line2{0}Line3", Environment.NewLine);

    is the correct way to do it.
  • dkf 2008-02-15 08:43
    sobani:
    MacOS has:
    "\r"
    In OS9 that was true, but OSX uses a Unix-style LF as a line separator.
  • Eric Shinn 2008-02-15 08:44
    Reminds me of a WTF I saw the other day; if you output a CSV file and open it in Excel, Microsoft expects \r\n between rows but just \n for a newline within a cell. Of course if you open the CSV in Notepad it wants \r\n everywhere. Bah.
  • Anonymous 2008-02-15 08:46
    The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".
  • Cosmin Marginean 2008-02-15 08:48
    Considering what I've seen on thedailywtf, I am expecting something like this any day now:
    public static string CHAR_A
    {
    get
    {
    char chrCR = 'A';
    string strCR = chrCR.ToString();
    return strCR;
    }
    }

    public static string CHAR_B
    {
    get
    {
    char chrCR = 'B';
    string strCR = chrCR.ToString();
    return strCR;
    }
    }
    ...
    public static string CHAR_SPACE
    {
    get
    {
    char chrCR = ' ';
    string strCR = chrCR.ToString();
    return strCR;
    }
    }
    ...
  • Grovesy 2008-02-15 08:52
    joe.edwards@imaginuity.com:
    On Windows platforms, "\r\n" == Environment.NewLine. If you know the only platform your software will run on is Windows (e.g. server-side code), then there's no real distinction.



    Personally, I nearly always go down the \r\n route... just looks tidier (if any of my code is around in 47 years, and Microsoft decided to go with one char for new lines instead of the two.. I'm very very sorry for creating the '2050 new line feed bug...'

    Only because I'll be 70 and probably won't be working then to cash in on the insane contractor rates we saw with the millennium bug
  • You'll also need... 2008-02-15 08:53
    Cosmin Marginean:
    Considering what I've seen on thedailywtf, I am expecting something like this any day now:
    public static string CHAR_A
    {
    get
    {
    char chrCR = 'A';
    string strCR = chrCR.ToString();
    return strCR;
    }
    }

    public static string CHAR_B
    {
    get
    {
    char chrCR = 'B';
    string strCR = chrCR.ToString();
    return strCR;
    }
    }
    ...
    public static string CHAR_SPACE
    {
    get
    {
    char chrCR = ' ';
    string strCR = chrCR.ToString();
    return strCR;
    }
    }
    ...

    What about non latin-based alphabets? You must define a character-supplier interface, and implement it for all character sets. Then you will need a factory to produce the right type of "supplier". Of course, it must all be configurable via xml in case they come up with a new character set, or in case we meet and start working with space aliens who don't happen to use any of the ones we use!
  • sobani 2008-02-15 08:58
    dkf:
    sobani:
    MacOS has:
    "\r"
    In OS9 that was true, but OSX uses a Unix-style LF as a line separator.

    OK, MacOS used to have:
    "\r"
    :-P

    Anyway, a few years back the "\r" bit me when I used javascript to parse some user input.

    Back then, when I was still young and clueless...

    sobani,
    Living proof the clueless part doesn't auto-update when years pass :-/
  • Mizchief 2008-02-15 08:59
    I would do it this way:

    myString = string.Format("Line1{0}Line2{0}Line3", Environment.NewLine);

    StringBuilders use too much overhead and are unesscarry in most cases.
  • fanguad 2008-02-15 09:00
    You'll also need...:
    What about non latin-based alphabets? You must define a character-supplier interface, and implement it for all character sets. Then you will need a factory to produce the right type of "supplier". Of course, it must all be configurable via xml in case they come up with a new character set, or in case we meet and start working with space aliens who don't happen to use any of the ones we use!


    Don't be ridiculous. All space aliens speak English and have American accents.
  • Grovesy 2008-02-15 09:00
    John:
    No

    myString = string.Format("Line1{0}Line2{0}Line3", Environment.NewLine);

    is the correct way to do it.


    As the compiler will resolve


    string s1 = "line1" + enviroment.newline + "line2";

    string s2 = "line1\r\nline2";


    to the same thing at compile time (I belive... Enviroment.NewLine is either a constant, or a read only static variable. It should work out that they are both the same string, intern it and point both variables at the one value.



    string s = String.Format("line1{0}line2", Enviroment.NewLine);

    You are basicaly under the covers saying

    StringBuilder sb = new StringBuilder();
    sb.Append("line1");
    sb.Append(Enviroment.NewLine);
    sb.Append("line2");
    return sb.ToString();

    Unless, the compiler is really really clever, this is going to have to be worked out at runtime.

    I'm sure someone will correct me with the StringBuilder argument if I'm wrong.. it's been a while since I've read up on strings and .net

  • Mythokia 2008-02-15 09:01
    Wow! I didn't even know Environment.NewLine existed until I read this article. I've always been using \n.
  • Jason 2008-02-15 09:02
    I've actually seen some .NET books teach using /n as the way to generate a new line instead of the "correct way."
  • Grovesy 2008-02-15 09:05
    Mizchief:
    I would do it this way:

    myString = string.Format("Line1{0}Line2{0}Line3", Environment.NewLine);

    StringBuilders use too much overhead and are unesscarry in most cases.


    String.Format uses StringBuilder.

    Which is why you should never ever do

    StringBuilder sb = new ...

    ...
    sb.Append(String.Format("hello {0}", someString);

    A second string builder is created.
  • Anon 2008-02-15 09:14
    I hope you mean "\n" not "/n" !?
  • Greg Beech 2008-02-15 09:14
    Constants and read-only statics are different.

    Constants are replaced at compile time, because they are constant and can be.

    The whole point of read-only statics is that they are NOT replaced at compile-time because they may not be constant (as Environment.NewLine isn't).

    So your concatenation examples are not the same.
  • DOA 2008-02-15 09:15
    Reminds me of when I first started working and I had to connect to a remote app. For reasons that I barely remember I chose to simply open a socket and poured properly formatted text in it. I was using a linux system and the remote app was running on a windows machine. At the time I had no idea that different OSes used different characters for line returns and spent a day or two wondering why the hell the remote system wouldn't do what it was supposed to do.
    There was a lot of cursing when I finally figured it out...
  • Grovesy 2008-02-15 09:20
    Greg Beech:
    Constants and read-only statics are different.

    Constants are replaced at compile time, because they are constant and can be.

    The whole point of read-only statics is that they are NOT replaced at compile-time because they may not be constant (as Environment.NewLine isn't).

    So your concatenation examples are not the same.


    Just realised that shortly have hitting post.. :)

    Anyhow, checking .net documentation... It is a Constant according to MSDN.
  • Aaron 2008-02-15 09:25
    Anonymous:
    The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".

    For the same reason that:
    int x = 28;

    is the wrong way, and...

    private const int MinDaysInMonth = 28;
    
    // (later on)
    int daysInMonth = MinDaysInMonth;

    ...is the right way.

    In other words, the right way is to not be a lazy waste of skin, and instead take the extra 5 seconds to type out an extra couple of characters/words that will save the poor sap tasked with maintaining your piss-poor code a good half-hour or more.

    Get it?
  • Alan 2008-02-15 09:29
    Grovesy:

    As the compiler will resolve


    string s1 = "line1" + enviroment.newline + "line2";

    string s2 = "line1\r\nline2";


    to the same thing at compile time (I belive... Enviroment.NewLine is either a constant, or a read only static variable. It should work out that they are both the same string, intern it and point both variables at the one value.

    Bear in mind that compiletime == runtime for in .NET speak. Your code is compiled *as required*. Therefore you won't condense enviroment.newline to the correct character (or char sequence) until runtime, so on all platforms you'll get the correct sequence.
  • XIU 2008-02-15 09:29
    Grovesy:
    Just realised that shortly have hitting post.. :)

    Anyhow, checking .net documentation... It is a Constant according to MSDN.


    It's not a constant, it's even a property.
  • Kiss me I'm Polish 2008-02-15 09:30
    DEFINE \n Environment.NewLine
  • aliquam 2008-02-15 09:32
    Better do it the right way+Environment.NewLine++Environment.NewLine+Else we might end up on here.+Environment.NewLine+I'm just glad he didn't do something like+Environment.NewLine+
    public static string CRLF
    {
    get
    {
    return Environment.NewLine;
    }
    }
    +Environment.NewLine++Environment.NewLine+That might have been as funny as him casting a char to convert into a string on multiple lines...
  • Buddy 2008-02-15 09:33
    Actually, I've done similar - maybe not so verbose.

    If you don't know which platform your code will run on, but you absolutely need to be certain that you write a CR/LF pair (or any kind of line termination) because you know what platform will read the file, specifying each character explicitly is the only way.

    In C, I'd use something like this:

    #define CRLF "\x0d\x0a"

    ...

    fprintf(file, "Ghastly weather%s" CRLF, (emphasize)? "!": ".");
  • Wyatt 2008-02-15 09:35
    Carra:
    The real WTF is not using a StringBuilder!


    For all the StringBuilder fans,
    myString = "Line1" + Environment.NewLine + "Line2" + Environment.NewLine + "Line3";

    gets emitted as a single call to string.Concat() with all the different parts as parameters. This largely negates any benefit you might see from StringBuilder.
  • GalacticCowboy 2008-02-15 09:38
    A Nonny Mouse:
    when a vb developer meets .net, coming through the rye..


    No, it's C#... VB has vbCrLf.
  • Rick 2008-02-15 09:40
    sobani:
    Windows has:
    "\r\n"

    Linux has:
    "\n"

    MacOS has:
    "\r"

    That's why you should use the Right Way instead of the Easy Way.


    There is extra credit for giving VMS end of line code. (hint, none of the above.)
  • alunharford 2008-02-15 09:45
    It completely blows away any benefits you might see from a StringBuilder. It's >10x faster, and much clearer.
  • Martin 2008-02-15 09:48
    Anonymous:
    The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".


    It looks like that is the way .net is going. Anyone seen this :http://www.charlespetzold.com/etc/CSAML.html
  • Aaron 2008-02-15 09:50
    Grovesy:
    String.Format uses StringBuilder.

    Which is why you should never ever do

    StringBuilder sb = new ...

    ...
    sb.Append(String.Format("hello {0}", someString);

    A second string builder is created.

    Why should you "never ever" do that? Is there a shortage of StringBuilders that nobody has told me about?

    What if you're creating an error report that's 500 lines long and 20 of those lines have a few tokens to replace, like system info and such? Should you replace the entire thing with one string.Format(...) call with 50 parameters? Or are you instead suggesting that we replace the original 20 Format()ed lines with 80 repetitive Append calls?

    The purpose of a StringBuilder is to avoid the exponential performance associated with a pantload of immutable concatenations. So something like:

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 5000; i++)
    {
    sb.Append("Hello, " + "there.")
    }

    is still far, far better than the old

    string s = string.Empty;
    for (int i = 0; i < 5000; i++)
    {
    s = s + "Hello, " + "there.";
    }

    Yes, both ways are stupid in this contrived example, and if you are writing a really tight loop (which most people reading this have probably never had to write), then you might want to start worrying about things like this. But for the vast majority of programmers and programs, the important concept is just to use the mutable StringBuilder rather than creating the same immutable string over and over again through concats. It doesn't really matter if you use a regular old concat or Format() to feed one individual line to the StringBuilder.

    There's a balance to maintain between performance and code readability. Maybe you really need to optimize the hell out of some chunk of string-twiddling code, but maybe you don't, so never say never.
  • alien 2008-02-15 09:51
    i dont
  • Grovesy 2008-02-15 09:52
    [quote user="XIU"][quote user="Grovesy"]Just realised that shortly have hitting post.. :)

    Anyhow, checking .net documentation... It is a Constant according to MSDN.[/quote]

    Thought I had better check this up, using C# with VS2005 against the .net 2 framework, taking the following code.. we get the following outputs after compilation

    public static void f1()
    {
    string x = "hello\r\nworld";
    }

    public static void f2()
    {
    string x = "hello" + Environment.NewLine + "world";
    }

    public static void f3()
    {
    string x = "hello" + "\r\n" + "world";
    }

    public static void f4()
    {
    string.Format("hello{0}world", "\r\n");
    }
    public static void f5()
    {
    string.Format("hello{0}world", Environment.NewLine);
    }
    public static void f6()
    {
    StringBuilder sb = new StringBuilder();
    sb.Append("hello");
    sb.Append(Environment.NewLine);
    sb.Append("world");
    }


    We have the following IL

    .method public hidebysig static void f1() cil managed
    {
    // Code size 8 (0x8)
    .maxstack 1
    .locals init ([0] string x)
    IL_0000: nop
    IL_0001: ldstr "hello\r\nworld"
    IL_0006: stloc.0
    IL_0007: ret
    } // end of method Program::f1

    .method public hidebysig static void f2() cil managed
    {
    // Code size 23 (0x17)
    .maxstack 3
    .locals init ([0] string x)
    IL_0000: nop
    IL_0001: ldstr "hello"
    IL_0006: call string [mscorlib]System.Environment::get_NewLine()
    IL_000b: ldstr "world"
    IL_0010: call string [mscorlib]System.String::Concat(string,
    string,
    string)
    IL_0015: stloc.0
    IL_0016: ret
    } // end of method Program::f2


    .method public hidebysig static void f3() cil managed
    {
    // Code size 8 (0x8)
    .maxstack 1
    .locals init ([0] string x)
    IL_0000: nop
    IL_0001: ldstr "hello\r\nworld"
    IL_0006: stloc.0
    IL_0007: ret
    } // end of method Program::f3

    .method public hidebysig static void f4() cil managed
    {
    // Code size 18 (0x12)
    .maxstack 8
    IL_0000: nop
    IL_0001: ldstr "hello{0}world"
    IL_0006: ldstr "\r\n"
    IL_000b: call string [mscorlib]System.String::Format(string,
    object)
    IL_0010: pop
    IL_0011: ret
    } // end of method Program::f4

    .method public hidebysig static void f5() cil managed
    {
    // Code size 18 (0x12)
    .maxstack 8
    IL_0000: nop
    IL_0001: ldstr "hello{0}world"
    IL_0006: call string [mscorlib]System.Environment::get_NewLine()
    IL_000b: call string [mscorlib]System.String::Format(string,
    object)
    IL_0010: pop
    IL_0011: ret
    } // end of method Program::f5


    .method public hidebysig static void f6() cil managed
    {
    // Code size 44 (0x2c)
    .maxstack 2
    .locals init ([0] class [mscorlib]System.Text.StringBuilder sb)
    IL_0000: nop
    IL_0001: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
    IL_0006: stloc.0
    IL_0007: ldloc.0
    IL_0008: ldstr "hello"
    IL_000d: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    IL_0012: pop
    IL_0013: ldloc.0
    IL_0014: call string [mscorlib]System.Environment::get_NewLine()
    IL_0019: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    IL_001e: pop
    IL_001f: ldloc.0
    IL_0020: ldstr "world"
    IL_0025: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    IL_002a: pop
    IL_002b: ret
    } // end of method Program::f6
  • [ICR] 2008-02-15 09:53
    "string s = String.Format("line1{0}line2", Enviroment.NewLine);

    You are basicaly under the covers saying

    StringBuilder sb = new StringBuilder();
    sb.Append("line1");
    sb.Append(Enviroment.NewLine);
    sb.Append("line2");
    return sb.ToString(); "

    Actually, it's saying

    StringBuilder sb = new StringBuilder(21);
    sb.AppendFormat(null, format, new object[] {Environment.NewLine});
    return sb.ToString();

    But that's just being pedantic.

    And Environment.NewLine isn't a constant, it's a property, and thus can't be inlined.

    If you are just adding strings then "String1" + Environment.NewLine + "String2" is the best way. If you are doing it in a loop, say:
    for(int i = 0; i < 10; i++)
    {
    stringBuilder.Append("String" + i);
    }
    Then a StringBuilder is generally best. If you are doing something which concatenates a lot of strings in a potentially confusing way, then string.Format might be good:
    string printOut = string.Format(@"Name: {0} D/O/B: {1} Rank: {2}", name, dob.ToShortDateString(), rank);
    Here the syntax of the content of the string is much clearer, and we don't need to pollute it with things like our conversion of the date to a string.
  • WhiskeyJack 2008-02-15 09:58
    Aaron:
    private const int MinDaysInMonth = 28;
    
    // (later on)
    int daysInMonth = MinDaysInMonth;

    ...is the right way.

    In other words, the right way is to not be a lazy waste of skin, and instead take the extra 5 seconds to type out an extra couple of characters/words that will save the poor sap tasked with maintaining your piss-poor code a good half-hour or more.

    Get it?


    Or, we could NOT fill our programs with global variables for no good reason. Do we expect the "min days in month" to one day change as the world moves to a new kind of calendar? Now when I debug this code I see that assignment and I have to do another code search to find MinDaysInMonth.


    int daysInMonth = 28; // minimum number of days in a month



    If this value is used in multiple places, THEN of course it makes sense to declare it as a class variable or global.
  • Jim 2008-02-15 09:58
    Anonymous:
    The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".


    It beats Java:

    System.getProperty("environment.newline");

    43 characters...And doing it in Java is more important as well, as it is cross platform, as opposed to .NET, which is Windows only. using "\n" is safe in .NET, as that is the windows newline for everything except notepad, which expects "\r\n".

    And I am aware of the Mono project to bring .NET out to everyone else, but that's not supported by Microsoft, who is really, the owners of .NET. Just because I can run World of Warcraft on Linux using Wine doesn't make it a Linux product, so running .NET on Linux/Mac using Mono doesn't make it a Linux product either.
  • SlyEcho 2008-02-15 10:03
    Grovesy:



    string s = String.Format("line1{0}line2", Enviroment.NewLine);


    You are basicaly under the covers saying


    StringBuilder sb = new StringBuilder();
    sb.Append("line1");
    sb.Append(Enviroment.NewLine);
    sb.Append("line2");
    return sb.ToString();



    More like:


    StringBuilder sb = new StringBuilder();
    sb.AppendFormat("line1{0}line2", Enviroment.NewLine);
    return sb.ToString();


    Grovesy:

    Unless, the compiler is really really clever, this is going to have to be worked out at runtime.


    Well, that would be a good thing if you wanted to run the same program on different platforms without recompiling.
  • Cosmin Marginean 2008-02-15 10:06
    You'll also need...:
    Cosmin Marginean:
    Considering what I've seen on thedailywtf, I am expecting something like this any day now:
    public static string CHAR_A
    {
    get
    {
    char chrCR = 'A';
    string strCR = chrCR.ToString();
    return strCR;
    }
    }

    public static string CHAR_B
    {
    get
    {
    char chrCR = 'B';
    string strCR = chrCR.ToString();
    return strCR;
    }
    }
    ...
    public static string CHAR_SPACE
    {
    get
    {
    char chrCR = ' ';
    string strCR = chrCR.ToString();
    return strCR;
    }
    }
    ...

    What about non latin-based alphabets? You must define a character-supplier interface, and implement it for all character sets. Then you will need a factory to produce the right type of "supplier". Of course, it must all be configurable via xml in case they come up with a new character set, or in case we meet and start working with space aliens who don't happen to use any of the ones we use!

    Damn you're right. I've been waiting a long time for something like:
    CharsetProviderFactory factory = CharsetProviderFactory.getXmlProviderFactory();
    charset = factory.getCharsetProvider("/home/looser/pluto-dialect.xml");
    String message = charset.I + charset.SPACE + charset.A + charset.M + charset.SPACE + charset.R + charset.E + charset.T + charset.A + charset.R + charset.D + charset.E + charset.D + charset.BACKSLASH + charset.ALIEN_SMILEY;
  • rick 2008-02-15 10:07
    I've seen where newlines needed to be coded /r/n btw hence the Environment.Newline
  • Grovesy 2008-02-15 10:09
    [ICR]:
    "string s = String.Format("line1{0}line2", Enviroment.NewLine);

    You are basicaly under the covers saying

    StringBuilder sb = new StringBuilder();
    sb.Append("line1");
    sb.Append(Enviroment.NewLine);
    sb.Append("line2");
    return sb.ToString(); "

    Actually, it's saying

    StringBuilder sb = new StringBuilder(21);
    sb.AppendFormat(null, format, new object[] {Environment.NewLine});
    return sb.ToString();

    But that's just being pedantic.

    And Environment.NewLine isn't a constant, it's a property, and thus can't be inlined.

    If you are just adding strings then "String1" + Environment.NewLine + "String2" is the best way. If you are doing it in a loop, say:
    for(int i = 0; i < 10; i++)
    {
    stringBuilder.Append("String" + i);
    }
    Then a StringBuilder is generally best. If you are doing something which concatenates a lot of strings in a potentially confusing way, then string.Format might be good:
    string printOut = string.Format(@"Name: {0} D/O/B: {1} Rank: {2}", name, dob.ToShortDateString(), rank);
    Here the syntax of the content of the string is much clearer, and we don't need to pollute it with things like our conversion of the date to a string.


    Just to be clear, I have nothing against string.format or stringbuilder .. when used in correctly (I’ve met too many developers who String Build everything together). Or use string.format on string literals. StringBuilders that in turn call string.format will cause unnecessary garbage. Not a problem, only in extremely high load (we have an emailing system that knocks out some 100+ emails a second at peak times.. order confirmations, cancelations, delivery notifications, etc, we’d rather as little garbage to be cleaned up as possible)

    In terms of the NewLine being a constant, according to MSDN it is a constant in each version of the Framework (which I can't help thinking is a WTF), but wrapped up in a static property. I thought (incorrectly) that the compiler figured this out (the above IL output shows me to be wrong :)
  • loh 2008-02-15 10:12
    VMS: none -> all

    Default text was variable-length record (embedded line length), but you could create "stream" format files and set the line ending to any of the CR, LF, or CRLF formats. Most basic utilities could use them as-is. This was added at least by version 5, I believe, to make cross-OS file access simpler.

    It's been a while, so I probably have the syntax wrong:

    $ create file /format=stream_cr
    $ create file /format=stream_lf
    $ create file /format=stream (CRLF)

    And let's not forget the various other RMS record formats (fixed, variable, variable with fixed control, fortran carriage control, indexed, ...).

    Now I'm just misty with nostalgia, lol.
  • Yep 2008-02-15 10:17
    My company still develops a product that runs on VMS and our customers continue to purchase new Vax/VMX platforms.
  • Karellen 2008-02-15 10:29
    Well, in C and C-derived languages, the correct way is the same as the easy way. It's just:

    myString = "Line1\nLine2\nLine3";

    If this string is written to a file, stream, socket, etc... that has been opened in text mode, "\n" in the string should be converted into the platform's newline sequence. Similarly, when reading, the platform's newline sequence should be converted to a "\n" for the programmer.

    This is why you seek()/fseek() has quirks when working with text-mode files on platform's newline sequence is not a single byte.

    Of course, UNIX makes things easy by requiring that '\n' is a single byte.
  • MadQ 2008-02-15 10:33
    I'm suprised that nobody has touched on this yet:
    string text = @"Line0
    
    Line1";

    Clearly, there's a newline in that verbatim string literal. Now it just depends on how the file was saved. US-ASCII? UTF8 with Unicode Line Separator or Paragraph separator?

    Suppose you saved the file on Unix, and then I save it on Windows. Now the source code looks the same to both of us, but we end up with different string literals in the compiled IL.

    I don't think there's one single Right Way™. There's a recommended way, and then there's the Right Way™ for your particular project.

    The recommended way might not be suitable if you do a lot of string processing. Every time you call String.Concat() (which is how string + string gets translated), you're allocating a new string. Doing that a few hundred thousand times will give the garbage collector a good workout.
  • Paolo G 2008-02-15 10:35
    "codeier"? That would be the comparative of "codey", right? Adjectives ending in -y form the comparative and superlative using -ier and -iest, and so do adjectives ending in -ey. So "codey" -> "codier", "codiest".
  • [ICR] 2008-02-15 10:41
    "In terms of the NewLine being a constant, according to MSDN it is a constant in each version of the Framework (which I can't help thinking is a WTF), but wrapped up in a static property. I thought (incorrectly) that the compiler figured this out (the above IL output shows me to be wrong :)"

    The problem with that is that if Microsoft ever decide to change what NewLine returns then all the existing code would break because the value was baked in there. Not really a problem in this case because the best way to switch between NewLines is using an ifdef (as indeed they do) but there are plenty of situations where it could potentially break, and obviously the compiler can't tell intent.

    Obviously, though, that's not the reason the optimisation isn't done because you get the same problem with constants and local constant/literal properties, where that wouldn't be a problem, aren't inlined.
  • Boris 2008-02-15 10:41
    Oh please no. How exactly would you program in something like this? I mean with XAML you can create it all in a visual designer, but actual programming functions? To quote one example,
    A = 5 * (B + 27 * C);
    I mean anyone who knows simple algebra would understand this (minus the semicolon in the end maybe). And no one will ever forget what = means (at least in the context of a single programming language). How the heck are you supposed to remember <Assignment.Expression>? And this is a "simple" example.
  • [ICR] 2008-02-15 10:47
    [Continued, submitted too soon].
    The answer as to why it's not inlined is most likely because it is inlined when it is jitted (http://blogs.msdn.com/ericgu/archive/2004/01/29/64644.aspx).

    Jitting confuses any discussion like this on optimisations, because all people tend to go on is IL as though that were interpreted straight, when in reality there is a whole other set of optimisations that occur after.
  • GregP 2008-02-15 11:00
    I used the enviroment.newline once and with each character I typed I felt more and more like it was a WTF. (I also used DirectorySeparatorChar for good measure)

    But, aside from the fact that everyone's doing it wrong, when is this going to change?

    Now if this were Java or some other cross platform technology I could see add this, but it's not like MS is going to wake up one morning and say "why don't we make it easy for people to write linux apps in .Net?"

    Unless the character sequence changes between Windows versions, I don't see why they even wasted their time on it.
  • Thief^ 2008-02-15 11:01
    DOA:
    Reminds me of when I first started working and I had to connect to a remote app. For reasons that I barely remember I chose to simply open a socket and poured properly formatted text in it. I was using a linux system and the remote app was running on a windows machine. At the time I had no idea that different OSes used different characters for line returns and spent a day or two wondering why the hell the remote system wouldn't do what it was supposed to do.
    There was a lot of cursing when I finally figured it out...

    Yeah, e.g. all HTTP communication is supposed to use the windows-style newlines between headers, but the server is supposed to be able to process plain \n or \r.
    The best part is that _after_ the headers can be binary data or text with different line endings, and this SHOULDN'T be fucked with by the client or server.
  • rootbeer22 2008-02-15 12:02
    If using the C convention, shouldn't \n already be translated to the correct control character(s) for the host platform?

    "Newline" and "linefeed" are not equivalent (even if Unix folks sometimes assume they are). If the difference is respected, "\r\n" on a DOS/Windows platform /should/ result in CR-CR-LF, not just CR-LF.

  • Nathan 2008-02-15 12:08
    May the code was for a mailserver? SMTP server often insist on receiving a CRLF at the end of each line... The Environment.Newline constant isn't always CRLF, so it would be broken.
  • CoyneT 2008-02-15 13:34
    WhiskeyJack:
    Aaron:
    private const int MinDaysInMonth = 28;
    
    // (later on)
    int daysInMonth = MinDaysInMonth;

    ...is the right way.

    In other words, the right way is to not be a lazy waste of skin, and instead take the extra 5 seconds to type out an extra couple of characters/words that will save the poor sap tasked with maintaining your piss-poor code a good half-hour or more.

    Get it?


    Or, we could NOT fill our programs with global variables for no good reason. Do we expect the "min days in month" to one day change as the world moves to a new kind of calendar? Now when I debug this code I see that assignment and I have to do another code search to find MinDaysInMonth.


    int daysInMonth = 28; // minimum number of days in a month



    If this value is used in multiple places, THEN of course it makes sense to declare it as a class variable or global.


    I agree, limited. The problem is taking care to discern what WILL change and what WILL NOT.

    Take for example Y2K, and the assumption that 2 digits is enough for year: I was actually told once (about 1983), "Don't worry about 2000. That's 17 years from now and you probably won't even be here then."

    If there's anything that is a "constant" in programming, it's change. I've learned the hard way that nearly every program, no matter how trivial, needs to change sooner or later...even the ones I thought were for "one time use".

    Global constants can also do things for you such as save all that typing. Don't like "Environment.NewLine"? How about:


    String nl = Environment.NewLine;

    myString = "Line1"+nl+"Line2"+nl+"Line3";



    See, that way you get the portability with much less pain. Just because "they" have to be wordy to meet namespace requirements doesn't mean you have to be wordy.
  • Lastchance 2008-02-15 13:40
    Martin:
    Anonymous:
    The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".


    It looks like that is the way .net is going. Anyone seen this :http://www.charlespetzold.com/etc/CSAML.html

    I saw what you did there.
  • Aaargh! 2008-02-15 14:20
    Jim:
    Anonymous:
    The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".

    It beats Java:

    System.getProperty("environment.newline");

    43 characters...And doing it in Java is more important as well, as it is cross platform, as opposed to .NET, which is Windows only.

    Actually, that's the wrong way. The right way would be to use a PrintWriter's println() method when writing to the screen, or a BufferedWriter around a FileWriter when writing to a file. (And the accompanying Readers when reading)

    Not only do they output the correct newline's, they also do conversion from Java's internal String format (Unicode, IIRC) to the platform's default character encoding (or any other encoding if you want. Encoding is done somewhere in the underlying OutputStreamWriter). You're all assuming
    you're writing to a terminal that understands ASCII or something similar. But the users terminal could be in EBCDIC for all you know.

    /Too bad this post wil bump the reply count from 64 to 65 :-/
  • Aaron 2008-02-15 14:38
    WhiskeyJack:
    Or, we could NOT fill our programs with global variables for no good reason. Do we expect the "min days in month" to one day change as the world moves to a new kind of calendar? Now when I debug this code I see that assignment and I have to do another code search to find MinDaysInMonth.

    There are several things wrong with this response:

    1) The example is declared "const" - therefore, it's obviously not a variable.

    2) It's declared "private", which means it obviously does not have global scope.

    3) The primary reason for having a constant is not in case the value changes. On the contrary, if something is declared "const" then it is expected that the value is, well, constant. If it is expected to change at any time, then it should be externalized.

    4) "MinDaysInMonth" might very well change, not because of the world switching to a new calendar, but because of a leap year. Not that you'd want to declare a mutable value as a constant anyway, but I felt like nitpicking.

    5) Intellisense will show you the value of this constant with a simple mouse hover, and/or take you directly to the definition with one click. There is no "search" unless you're one of those pretentious reactionaries who insists on using junk tools like vi, and even then - boo hoo, you wasted 5 seconds of your day.

    6) It's a constant. Why would you ever need to look up the exact definition, unless you were already certain that it was declared incorrectly?

    7) Your counterexample of:

    int daysInMonth = 28; // minimum number of days in a month


    ...is a perfect example of a bad comment. The comment appears to be imply that the variable "daysInMonth" is actually supposed to contain the minimum number of days in a month; in my example, it's clear that this is simply an initial value. In addition, even if the comment were re-written to be more self-explanatory, you'd have to write this comment every time you used the magic number 28. Why would you do this?

    Think about scientific constants like Planck's Constant (h) or the Boltzmann Constant (K). There's a reason why we have special symbols for these constants - you don't want to be turning in a research paper with a little note in the margin every time one of the constants is used. You just write the equations with the corresponding symbol instead. Even if you only ever use the constant once, you still use the constant, not the exact quantity it represents.

    What does a scientific research paper have to do with code? Everything. Both of them are supposed to be written so as to be readable by someone else in the future. Defining specific constants and referencing them later is far, far preferable to using magic numbers and writing explanatory notes whenever they're used (or just writing the explanatory note once, and hoping that the reader retains it in memory and doesn't skim past the first explanation).

    I'll finish by re-hashing the old cliché: The Real WTF™ is, apparently, in the comments.
  • kobayashi 2008-02-15 14:43
    Except that Windows implicitly converts a "\n" to "\r\n" if the file is opened in text mode. So both "\n" and "\r\n" do the same thing. Linux does no conversion. So, if you code "\n", you get the same result regardless of whether it's run on Linux or Windows. And we all know that Macs will never be used for enterprisey types of applications.
  • e cho 2008-02-15 14:48
    I'm not buying your argument. Unlike your example, Environment.NewLine does not really provide additional clarification.

    We might as well require other frequently used items to be more verbose. How about using Operation.Multiply instead of *?
  • Barf 4 Eva 2008-02-15 15:03
    myString = "Line1" + Environment.NewLine + "Line2" + Environment.NewLine + "Line3";

    You should not require StringBuilder in this particular instance. You are not destroying myString string obj for every concatenation in this case, because you are not replacing it with itself + something. Only when you have variable "reuse" as such...

    myString += "Line1";
    myString += Environment.Newline;
    myString += "Line2";

    is it going to be problematic, because it destroys the old string obj and replaces it with the new one at every += operator.

    or...
  • NoOneKnows 2008-02-15 15:04
    Grovesy:
    Mizchief:
    I would do it this way:

    myString = string.Format("Line1{0}Line2{0}Line3", Environment.NewLine);

    StringBuilders use too much overhead and are unesscarry in most cases.


    String.Format uses StringBuilder.

    Which is why you should never ever do

    StringBuilder sb = new ...

    ...
    sb.Append(String.Format("hello {0}", someString);

    A second string builder is created.


    Plus there's always sb.AppendFormat() anyway.
  • Barf 4 Eva 2008-02-15 15:08
    Barf 4 Eva:

    or...


    oops... forgot to finish this line. :P

    Or maybe it depends on the compiler...? I've tested this scenario before over 100,000 iterations and performance change was not noticeable for sb.Append("1" + "2" + "3" + "4" + "5" + "6" + "7" + "8" + "9" + "10") vs sb.Append("12345678910"), where executed 100,000 times. whereas it was EXTREMELY noticeable for 100,000 iterations of myString += "12345678910"

    (I think it was 100,000... Been a while since I tested this. Hope I'm not remembering my test incorrectly. :P)
  • Matthew 2008-02-15 15:22
    joe.edwards@imaginuity.com:
    On Windows platforms, "\r\n" == Environment.NewLine. If you know the only platform your software will run on is Windows (e.g. server-side code), then there's no real distinction.


    In this case, it is actually better to be consistent than to conform to the conventions of the local OS. Imagine if you ran your program on Windows and generated a bunch of text files with CRLF. Then you moved the app to a Unix machine and couldn't parse those files properly because your parser is expecting just LF. It would be better if your program just always used CRLF or LF. Pick one and stick to it.
  • Mach58 2008-02-15 15:22
    FYI: There's no such thing as opening a file in "text mode" in Windows (don't know about linux). It's all just bytes, read from a stream. Various programs will interpret "\n", and "\r" as a newline, but the underlying controls (TextBox, etc.) require "\r\n" for a newline. You can see this with Notepad, which is more or less a wrapper around a textbox, plus some menus.

    There really is no reason to use En.NewLine over "\r\n" on Windows, and you should never use En.NewLine when dealing with protocols that require specific character sequences.

    I don't know what Mono returns for En.NewLine, and whether that changes on different OSes.
  • spork 2000 2008-02-15 15:43
    The real WTF™ is that you can't simply:
    A) write "\N" or something and have it translated to the appropriate format, or
    B) open the file in text mode and have the translation done on read/write.
  • Jazz 2008-02-15 15:45
    No, no, NO. The REAL WTF is Windows insisting on two characters for something that every sane platform can do in one. (Why have one byte when you can have two at twice the cost?)

    captcha: damnum
  • Teh Optermizar 2008-02-15 15:46
    Aaron:
    WhiskeyJack:
    Or, we could NOT fill our programs with global variables for no good reason. Do we expect the "min days in month" to one day change as the world moves to a new kind of calendar? Now when I debug this code I see that assignment and I have to do another code search to find MinDaysInMonth.

    There are several things wrong with this response:

    1) The example is declared "const" - therefore, it's obviously not a variable.

    2) It's declared "private", which means it obviously does not have global scope.

    3) The primary reason for having a constant is not in case the value changes. On the contrary, if something is declared "const" then it is expected that the value is, well, constant. If it is expected to change at any time, then it should be externalized.

    4) "MinDaysInMonth" might very well change, not because of the world switching to a new calendar, but because of a leap year. Not that you'd want to declare a mutable value as a constant anyway, but I felt like nitpicking.

    5) Intellisense will show you the value of this constant with a simple mouse hover, and/or take you directly to the definition with one click. There is no "search" unless you're one of those pretentious reactionaries who insists on using junk tools like vi, and even then - boo hoo, you wasted 5 seconds of your day.

    6) It's a constant. Why would you ever need to look up the exact definition, unless you were already certain that it was declared incorrectly?

    7) Your counterexample of:

    int daysInMonth = 28; // minimum number of days in a month


    ...is a perfect example of a bad comment. The comment appears to be imply that the variable "daysInMonth" is actually supposed to contain the minimum number of days in a month; in my example, it's clear that this is simply an initial value. In addition, even if the comment were re-written to be more self-explanatory, you'd have to write this comment every time you used the magic number 28. Why would you do this?

    Think about scientific constants like Planck's Constant (h) or the Boltzmann Constant (K). There's a reason why we have special symbols for these constants - you don't want to be turning in a research paper with a little note in the margin every time one of the constants is used. You just write the equations with the corresponding symbol instead. Even if you only ever use the constant once, you still use the constant, not the exact quantity it represents.

    What does a scientific research paper have to do with code? Everything. Both of them are supposed to be written so as to be readable by someone else in the future. Defining specific constants and referencing them later is far, far preferable to using magic numbers and writing explanatory notes whenever they're used (or just writing the explanatory note once, and hoping that the reader retains it in memory and doesn't skim past the first explanation).

    I'll finish by re-hashing the old cliché: The Real WTF™ is, apparently, in the comments.


    I concur with your findings.
  • Jay 2008-02-15 16:08
    [quote user="fanguad]Don't be ridiculous. All space aliens speak English and have American accents.[/quote]

    And every planet in the Galaxy looks suspiciously like southern California. Except for the planets you can reach via the Star Gate, which all look like British Columbia.
  • RAW 2008-02-15 16:10
    It's actually:

    System.getProperty("line.separator")

    but your point is still valid.

  • Jim 2008-02-15 16:30
    Aaargh!:
    Jim:
    Anonymous:
    The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".

    It beats Java:

    System.getProperty("environment.newline");

    43 characters...And doing it in Java is more important as well, as it is cross platform, as opposed to .NET, which is Windows only.

    Actually, that's the wrong way. The right way would be to use a PrintWriter's println() method when writing to the screen, or a BufferedWriter around a FileWriter when writing to a file. (And the accompanying Readers when reading)

    Not only do they output the correct newline's, they also do conversion from Java's internal String format (Unicode, IIRC) to the platform's default character encoding (or any other encoding if you want. Encoding is done somewhere in the underlying OutputStreamWriter). You're all assuming
    you're writing to a terminal that understands ASCII or something similar. But the users terminal could be in EBCDIC for all you know.

    /Too bad this post wil bump the reply count from 64 to 65 :-/


    Interesting - but what if you are doing neither of those things? i.e. generating some string to send to another system? Or, what if you are building some string that is being sent to log4j? It handles the file writing, etc...

    Your point is valid, you should use WriteLine methods when possible, as opposed to a Wrtie method with a new line appended. However, when constructing your own string that is being sent to some logging system, or across a raw socket, you can't exactly do that.
  • Jim 2008-02-15 16:33
    RAW:
    It's actually:

    System.getProperty("line.separator")

    but your point is still valid.



    Thanks pal, my bad. Still, 37 characters is more than the 18 for .NET, or the 2 for the wrong way. Myself, I usually create a final string in some utility class with a short name, so I can save the keystrokes, plus, it only looks up the property once. Plus, when we move to Java 5, I can use an import static on it.
  • Jay 2008-02-15 17:25
    Surely the real "What were you thinking?" is that OSes use different line-ending conventions. The computer world has pretty much standardized on ASCII as our universal character coding convention, extended to Unicode in an intelligent, upward-compatible way ... except that one of the most commonly-used characters, the line-end, we can't agree on. Ummm ... why not? But somehow we accept that every OS has a different value for end-of-line. And the Windows idea of requiring TWO characters for end-of-line is absolutely insane. Who was it who said, "Hey, I've got a good idea: Let's require a two-character sequence to mark end-of-line! That way, every program that anyone ever develops that reads text files will have to go through all sorts of extra complexity to deal with the possibility that we'll see only one of the two characters, and will have to decide how to interpret \n\r and \r\r\n, etc. Yeah, that will really make programming easier."

    Hey, I think that in my next program, when I write text files I'll use standard ASCII throughout except that for the letter "e", instead of the boring ASCII x65, I'll use x 11 32 47.
  • Gimpy 2008-02-15 17:29
    MadQ:
    I'm suprised that nobody has touched on this yet:
    string text = @"Line0
    
    Line1";

    Clearly, there's a newline in that verbatim string literal. Now it just depends on how the file was saved. US-ASCII? UTF8 with Unicode Line Separator or Paragraph separator?

    Suppose you saved the file on Unix, and then I save it on Windows. Now the source code looks the same to both of us, but we end up with different string literals in the compiled IL.

    I don't think there's one single Right Way™. There's a recommended way, and then there's the Right Way™ for your particular project.

    The recommended way might not be suitable if you do a lot of string processing. Every time you call String.Concat() (which is how string + string gets translated), you're allocating a new string. Doing that a few hundred thousand times will give the garbage collector a good workout.


    You know, we were doing an in-class assighnment in C# once, and we were lazy (let's just get it running so the teacher gives us our mark), so we tried that. It doesn't compile. In Java, if you hit enter in the middle of the string literal, it will automatically split the string into 2 literals with operator+ between them, and put the latter on the lower line. It doesn't even add the newline, it just assumes you are shortening the code line length, so you don't have a line running WAAAY off the screen.
  • VGR 2008-02-15 17:29
    Jim:
    RAW:
    It's actually:

    System.getProperty("line.separator")

    but your point is still valid.



    Thanks pal, my bad. Still, 37 characters is more than the 18 for .NET, or the 2 for the wrong way. Myself, I usually create a final string in some utility class with a short name, so I can save the keystrokes, plus, it only looks up the property once. Plus, when we move to Java 5, I can use an import static on it.


    You guys may want to put down that book printed in 1998, and look at some javadoc. Then you might learn about this:

    String s = String.format("Line1%nLine2%nLine3");
  • powerlord 2008-02-15 18:09
    Since I haven't seen this entire section quoted yet, I'm going to paste a chunk of the MSDN documentation for Environment.NewLine in .NET 2.0.

    Property Value
    A string containing "\r\n" for non-Unix platforms, or a string containing "\n" for Unix platforms.

    Remarks
    The property value of NewLine is a constant customized specifically for the current platform and implementation of the .NET Framework. For more information about the escape characters in the property value, see Character Escapes.

    The functionality provided by NewLine is often what is meant by the terms newline, line feed, line break, carriage return, CRLF, and end of line.

    NewLine can be used in conjunction with language-specific newline support such as the escape characters '\r' and '\n' in Microsoft C# and C/C++, or vbCrLf in Microsoft Visual Basic.

    NewLine is automatically appended to text processed by the System.Console.WriteLine and System.Text.StringBuilder.AppendLine methods.

    So, yes, it is a constant, but that constant is private to the API and must be accessed through its property.

    Also, from this documentation, Mono should implement Environment.NewLine as "\n".
  • powerlord 2008-02-15 18:27
    Mach58:
    FYI: There's no such thing as opening a file in "text mode" in Windows (don't know about linux).

    In the Win32 API, maybe not, but both C and C++ open files in text mode using their native open commands (fopen() and the fstream class).

    Which is interesting, since to UNIXes, binary and text files have the same line endings; it's DOS/Windows that differentiates between the two.
  • Mr Mr 2008-02-15 18:38
    sobani:
    Windows has:
    "\r\n"

    Linux has:
    "\n"

    MacOS has:
    "\r"

    That's why you should use the Right Way instead of the Easy Way.


    That depends. If you are trying to generate a CSV file, it is preferable to use \n. I don't like software generating different output on different platforms.

    But if you are writing to a console, the Right Way is the way to go.
  • Aaargh! 2008-02-15 18:43
    Jim:

    Interesting - but what if you are doing neither of those things? i.e. generating some string to send to another system?

    Depends on what you're doing and the format you should send your message in. There is a class called DataOutputStream which is very convenient if you have to communicate some data between two java apps. If it has to be text, you can just create an OutputStreamWriter with the correct encoding (it defaults to the system's default encoding but you can specify any of the encodings Java supports)

    Or, what if you are building some string that is being sent to log4j? It handles the file writing, etc...

    Log4J also uses the same mechanisms described before, simple because that's the way to do it in Java, furthermore, it's way more convenient to do it the right way than doing it the wrong way. Besides, it's Log4J's responsibility to do this the right way, not the callers'

    Your point is valid, you should use WriteLine methods when possible, as opposed to a Wrtie method with a new line appended. However, when constructing your own string that is being sent to some logging system, or across a raw socket, you can't exactly do that.

    Yes you can. You can always wrap a BufferedWriter around any other Writer. The BufferedWriter has a newLine() method which sends the correct newline character for the current platform.
  • Mr Mr 2008-02-15 18:47
    Jay:
    And the Windows idea of requiring TWO characters for end-of-line is absolutely insane..


    The origin of \r\n is actually from a time before Windows. Some printers used two different symbols to create a new line. First a CR to move to the left, and then a LF to move the paper to the next line.

    And there were other systems at the time that also did the same. At least it't not as bad as Apple's decision to use \r.

    Both Windows and Mac should have used \n because it was already a very common method of ending lines
  • xenoak47 2008-02-15 20:07
    Using .Net 3.5 extensions define:

    public static string ToEnviroString(this string str)
    {
    return str.Replace("\n", Environment.NewLine);
    }

    Then you can simply do:

    string result = "This\nIs\nA\nWord\nOn\nEvery\nLine".ToEnviroString();

    Done.
  • real_aardvark 2008-02-15 20:11
    And the real WTF is ... tadah!
    Grovesy:

    Thought I had better check this up, using C# with VS2005 against the .net 2 framework, taking the following code.. we get the following outputs after compilation

    public static void f1()
    {
    string x = "hello\r\nworld";
    }

    public static void f2()
    {
    string x = "hello" + Environment.NewLine + "world";
    }

    public static void f3()
    {
    string x = "hello" + "\r\n" + "world";
    }

    public static void f4()
    {
    string.Format("hello{0}world", "\r\n");
    }
    public static void f5()
    {
    string.Format("hello{0}world", Environment.NewLine);
    }
    public static void f6()
    {
    StringBuilder sb = new StringBuilder();
    sb.Append("hello");
    sb.Append(Environment.NewLine);
    sb.Append("world");
    }


    We have the following IL

    .method public hidebysig static void f1() cil managed
    {
    // Code size 8 (0x8)
    .maxstack 1
    .locals init ([0] string x)
    IL_0000: nop
    IL_0001: ldstr "hello\r\nworld"
    IL_0006: stloc.0
    IL_0007: ret
    } // end of method Program::f1

    .method public hidebysig static void f2() cil managed
    {
    // Code size 23 (0x17)
    .maxstack 3
    .locals init ([0] string x)
    IL_0000: nop
    IL_0001: ldstr "hello"
    IL_0006: call string [mscorlib]System.Environment::get_NewLine()
    IL_000b: ldstr "world"
    IL_0010: call string [mscorlib]System.String::Concat(string,
    string,
    string)
    IL_0015: stloc.0
    IL_0016: ret
    } // end of method Program::f2


    .method public hidebysig static void f3() cil managed
    {
    // Code size 8 (0x8)
    .maxstack 1
    .locals init ([0] string x)
    IL_0000: nop
    IL_0001: ldstr "hello\r\nworld"
    IL_0006: stloc.0
    IL_0007: ret
    } // end of method Program::f3

    .method public hidebysig static void f4() cil managed
    {
    // Code size 18 (0x12)
    .maxstack 8
    IL_0000: nop
    IL_0001: ldstr "hello{0}world"
    IL_0006: ldstr "\r\n"
    IL_000b: call string [mscorlib]System.String::Format(string,
    object)
    IL_0010: pop
    IL_0011: ret
    } // end of method Program::f4

    .method public hidebysig static void f5() cil managed
    {
    // Code size 18 (0x12)
    .maxstack 8
    IL_0000: nop
    IL_0001: ldstr "hello{0}world"
    IL_0006: call string [mscorlib]System.Environment::get_NewLine()
    IL_000b: call string [mscorlib]System.String::Format(string,
    object)
    IL_0010: pop
    IL_0011: ret
    } // end of method Program::f5


    .method public hidebysig static void f6() cil managed
    {
    // Code size 44 (0x2c)
    .maxstack 2
    .locals init ([0] class [mscorlib]System.Text.StringBuilder sb)
    IL_0000: nop
    IL_0001: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor()
    IL_0006: stloc.0
    IL_0007: ldloc.0
    IL_0008: ldstr "hello"
    IL_000d: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    IL_0012: pop
    IL_0013: ldloc.0
    IL_0014: call string [mscorlib]System.Environment::get_NewLine()
    IL_0019: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    IL_001e: pop
    IL_001f: ldloc.0
    IL_0020: ldstr "world"
    IL_0025: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string)
    IL_002a: pop
    IL_002b: ret
    } // end of method Program::f6

    Actually, this is technically quite interesting, and I don't mean to pick on Grovesy any more than on any other contributor to this thread ... but; two things.

    (1) This is crying out for generalisation via XML. I'm not a .NET man, but how about:

    XMLGubbins ("<line-terminator><locale={1}></locale>
    <machine={2}></machine>
    <os={3}></os>
    <version={4}></version>
    <year-of-our-lord={5}></year-of-our-lord>
    <quantity>One line terminator, please, kind sir
    </quantity>
    </line-terminator>") .ToString();


    I think that covers most of the possible variances and dependencies. It should really have a schema attached, and I don't know how to do interpolation in .NET, and obviously there's no such class as "XMLGubbins," although that will probably be rectified in .Net 4. But it seems, basically, to be the way to go.

    (2) Alternatively, we might consider taking a step back. What is the point of any of this? Who cares whether it's efficient or not? Pick any crap solution you want. Test it. If it's wrong, furtle it until it's right.

    Yes, people, the real WTF is that we're arguing about how to append an eol to a string.

    I have the sneaking suspicion that it might just be slightly more important that this loony has been let loose on other code; potentially more important code; potentially something like the odd financial transaction or two.

    An EOL is an EOL is an EOL. Get over it.
  • Bacon 2008-02-15 20:23
    http://en.wikipedia.org/wiki/Newline#History
  • mokus 2008-02-15 22:15
    Mythokia:
    Wow! I didn't even know Environment.NewLine existed until I read this article. I've always been using \n.


    This, I think, is the real issue with most of these "programmer X didn't use library Y, wtf!" posts. In the real world, programming tools change often, and when they do, the people who haven't seen them roll through for decades get very worked up when old habits don't die instantaneously.

    To what degree should a person be expected to go out of their way to inspect their habits and find out which ones are obsolete? If I type "\r\n", or use my own NewLine library, and it works (just like it has for the last 30 years), why should I look to see if there's a new system library for it every time I pick up a new language?

    For that matter, how often should I check with the Proper Authorities whether I'm tying my shoes properly?
  • MadQ 2008-02-15 22:30
    Gimpy:
    MadQ:
    I'm suprised that nobody has touched on this yet:
    string text = @"Line0
    
    Line1";

    ---snip---


    You know, we were doing an in-class assighnment in C# once, and we were lazy (let's just get it running so the teacher gives us our mark), so we tried that. It doesn't compile.
    ---snip---


    [In order to prove my intellectual superiority, I will now cite references...]

    If it didn't compile, then the compiler wasn't up to specs. See Standard ECMA-334, 4th Edition/June2006 note in §9.1 (page 65) on syntactic analysis and the last example of verbatim string literals in §9.4.4.5 (page 76.)

    Geez! Damn you for making me prove what a geek I am ;)

  • zzo38 2008-02-15 22:56
    John:
    No

    myString = string.Format("Line1{0}Line2{0}Line3", Environment.NewLine);

    is the correct way to do it.

    O, you're right (in my opinion anyways, if that works, probably it does but I don't know because I have never used .NET programming). If I ever make a program in .NET then I will try to remember that.
  • Stefan W. 2008-02-16 00:27
    VGR:
    Jim:
    RAW:
    It's actually:

    System.getProperty("line.separator")

    but your point is still valid.


    You guys may want to put down that book printed in 1998, and look at some javadoc. Then you might learn about this:

    String s = String.format("Line1%nLine2%nLine3");


    Sorry - I don't find %n on that page.
    And it doesn't work either.

    I allways use \n.
    Sooner or later MS will find out, that unix did it right in the first place.
    I don't support notepad - other editors handle \n gracefully on windows.
  • Soviut 2008-02-16 00:40
    Anonymous:
    The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".


    Because short code doesn't mean good code. Any decent IDE will auto-complete that by the time you've hit the letter "v", so technically it saves you one character of typing.
  • anonymous workaholic 2008-02-16 03:03
    mokus, the way it is supposed to work is that when you upgrade, you read the release notes. The release notes are where the developers of the new system describe which features have changed, which are deprecated etc. You don't need to re-read the entire manual to see what has changed. This is not only theory - this is how it works in the more competent corners of the industry.
  • hikari 2008-02-16 03:46
    Even String.Format() would have been an improvement.
  • hikari 2008-02-16 03:49
    If it didn't compile, then the compiler wasn't up to specs. See Standard ECMA-334, 4th Edition/June2006 note in §9.1 (page 65) on syntactic analysis and the last example of verbatim string literals in §9.4.4.5 (page 76.)


    My guess is they actually forgot the @ string-literal prefix when they did it.
  • Watson 2008-02-16 04:12
    Aaron:
    Should you replace the entire thing with one string.Format(...) call with 50 parameters? Or are you instead suggesting that we replace the original 20 Format()ed lines with 80 repetitive Append calls?
    Or maybe they're suggesting using StringBuilder.AppendFormat() instead?
  • Hans 2008-02-16 05:03
    fanguad:
    You'll also need...:
    What about non latin-based alphabets? You must define a character-supplier interface, and implement it for all character sets. Then you will need a factory to produce the right type of "supplier". Of course, it must all be configurable via xml in case they come up with a new character set, or in case we meet and start working with space aliens who don't happen to use any of the ones we use!


    Don't be ridiculous. All space aliens speak English and have American accents.


    Obviously you have not seen that old Star Trek episode where they encounter a parallel evolution of Nazis on an M-class planet...
  • JoeDelekto 2008-02-16 09:00
    On a momentary tangent, it still surprises me how many people ignore (usually under the guise of "pre-mature optimization" being the root of all evil) the true cost of things.

    In engineering school, the students are usually taught about not just the cost in terms of economic dollars, but in some cases, the amount of energy expended, the number of CPU cycles clicked, etc. In cases of abstraction where a lot of work for developers is now being handled by: a) the framework; and b) the compiler, the developer should still be cognizant of what is going on under the hood, since the abstraction of modern development tools merely shields people from the complexities of various algorithms as well as assists in the generation of boring and boilerplate code.

    For anyone that is at all remotely interested in using .NET, Lutz Roeder's Reflector should be the #1 tool in any .NET developer's toolchest.

    I created four simple C# static methods on the 'Main' object of a console application, using the various string concatenation methods that I've seen discussed here and weighed their cost using various criteria such as instructions used, function calls made, size of code, etc. I invite anyone using Reflector to see my findings as well, make sure you disassemble to "IL" code so you can see what the compiler truly generates.


    static void Test1()
    {
    string test1 = "part1" + Environment.NewLine + "part2" + Environment.NewLine + "part3" + Environment.NewLine;
    }

    static void Test2()
    {
    string newLine = Environment.NewLine;

    string test2 = "part1" + newLine + "part2" + newLine + "part3" + newLine;
    }

    static void Test3()
    {
    string newLine = Environment.NewLine;

    string test3 = String.Concat("part1", newLine, "part2", newLine, "part3", newLine);
    }

    static void Test4()
    {
    string test4 = String.Format("part1{0}part2{0}part3{0}", Environment.NewLine);
    }



    I found, after examining the generated IL of a release build, that Test2 and Test3 generated identical code. That's because using the '+' operator becomes a String.Concat() call. In that regard, using either method in Test2() or Test3() is a matter of coding standards or what might be considered most readable/understandable to the developer.

    Test1(), while also very readable, is highly inefficient, since every instance of Environment.Newline results in a function call to get the newline string for that environment.

    Test4(), by the way, is very readable, looks nice, sweet and compact. However, look at it under the hood with reflector. See that objects are created and constructed, functions called, processing done that's not visible unless one actually looks under the hood. String.Format() does indeed use a StringBuilder under the hood, because it is most efficient when dealing with a homogenous set of values that it might expect to find in a format specifier.

    StringBuilder, btw, is not a stigma, it does have some very good advantages when used to build large strings or strings that are non-deterministic due to logic within the flow of a program as well as being a conduit to marshal string data back and forth between non .NET code.

    <soapbox>

    Anyhow, my point is this: Never jump to conclusions based on readability of the code alone. Readable code is not necessarily the most optimal and premature optimization (which can make less-readable code) is also not necessarily the best path to choose. However, unless a developer is lazy and does not look at all the options to weigh them, they will not find a "happy medium" to choose between the two. Also, one has to understand the platform on which they are writing code. This includes not just your code, but also the operating system and in some cases, the CPU itself.

    Anyhow, in the grand scheme of things, most people who write code as professionals are not necessarily writing code for themselves, they are developing an application for a user. The end user doesn't care about how readable your code is (you should document confusing code), they just care about getting results and getting them as soon as humanly possible. <grin>
    </soapbox>


    Anyhow, I tend to like the code presented in Test3() myself.

  • CJudge 2008-02-16 12:33
    Martin:
    Anonymous:
    The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".


    It looks like that is the way .net is going. Anyone seen this :http://www.charlespetzold.com/etc/CSAML.html


    Perhaps you didn't notice the date of the Petzold article.
  • Coder 2008-02-16 13:34
    Programmers should not need to worry about how to write a newline. All students of programming go through these same new line and string builder issues, and that is waste of time of the humankind. I bet in no other field of expertise they think about newline 3 pages of posts with over hundred of comments...

    Why not create a character for newline. Empty character is "space". Then the newline character would be "new line", and you would get the newline by pressing certain key in keyboard and maybe with ctrl down or something. I mean, we have at-character, dollar-character, and even exclamation-character! Why not newline-character? How about Ascii 10: LF bound to somewhere in the keyboard and the system looks the system specific combination from a lookup table?

    The same goes with adding strings. If there is need for StringBuilder, why the programming language doesn't implement "+"-operation with StringBuilder in the first place?
  • Dan Neely 2008-02-16 15:09
    shouldn't this constant have been named cpCRLF?

    (cp = C Pound).
  • JaiDog 2008-02-16 17:43
    My company does extensive java development on VMS and let me tell you, it is a true joy to write the C code that the JNI calls to convert files to stream_lf...so java can read it.
  • Hamstray 2008-02-16 18:27
    there's yet still another obvious way:

    myString = "Line1
    Line2
    Line3";
  • Sean 2008-02-16 20:50
    sobani:
    Windows has:
    "\r\n"

    Linux has:
    "\n"

    MacOS has:
    "\r"

    That's why you should use the Right Way instead of the Easy Way.


    Nah, that's just the reason OSX and Windows are wrong.
  • real_aardvark 2008-02-16 21:00
    JoeDelekto:
    On a momentary tangent, it still surprises me how many people ignore (usually under the guise of "pre-mature optimization" being the root of all evil) the true cost of things.

    In engineering school, the students are usually taught about not just the cost in terms of economic dollars, but in some cases, the amount of energy expended, the number of CPU cycles clicked, etc. In cases of abstraction where a lot of work for developers is now being handled by: a) the framework; and b) the compiler, the developer should still be cognizant of what is going on under the hood, since the abstraction of modern development tools merely shields people from the complexities of various algorithms as well as assists in the generation of boring and boilerplate code.

    For anyone that is at all remotely interested in using .NET, Lutz Roeder's Reflector should be the #1 tool in any .NET developer's toolchest.

    I created four simple C# static methods on the 'Main' object of a console application, using the various string concatenation methods that I've seen discussed here and weighed their cost using various criteria such as instructions used, function calls made, size of code, etc. I invite anyone using Reflector to see my findings as well, make sure you disassemble to "IL" code so you can see what the compiler truly generates.


    static void Test1()
    {
    string test1 = "part1" + Environment.NewLine + "part2" + Environment.NewLine + "part3" + Environment.NewLine;
    }

    static void Test2()
    {
    string newLine = Environment.NewLine;

    string test2 = "part1" + newLine + "part2" + newLine + "part3" + newLine;
    }

    static void Test3()
    {
    string newLine = Environment.NewLine;

    string test3 = String.Concat("part1", newLine, "part2", newLine, "part3", newLine);
    }

    static void Test4()
    {
    string test4 = String.Format("part1{0}part2{0}part3{0}", Environment.NewLine);
    }



    I found, after examining the generated IL of a release build, that Test2 and Test3 generated identical code. That's because using the '+' operator becomes a String.Concat() call. In that regard, using either method in Test2() or Test3() is a matter of coding standards or what might be considered most readable/understandable to the developer.

    Test1(), while also very readable, is highly inefficient, since every instance of Environment.Newline results in a function call to get the newline string for that environment.

    Test4(), by the way, is very readable, looks nice, sweet and compact. However, look at it under the hood with reflector. See that objects are created and constructed, functions called, processing done that's not visible unless one actually looks under the hood. String.Format() does indeed use a StringBuilder under the hood, because it is most efficient when dealing with a homogenous set of values that it might expect to find in a format specifier.

    StringBuilder, btw, is not a stigma, it does have some very good advantages when used to build large strings or strings that are non-deterministic due to logic within the flow of a program as well as being a conduit to marshal string data back and forth between non .NET code.

    <soapbox>

    Anyhow, my point is this: Never jump to conclusions based on readability of the code alone. Readable code is not necessarily the most optimal and premature optimization (which can make less-readable code) is also not necessarily the best path to choose. However, unless a developer is lazy and does not look at all the options to weigh them, they will not find a "happy medium" to choose between the two. Also, one has to understand the platform on which they are writing code. This includes not just your code, but also the operating system and in some cases, the CPU itself.

    Anyhow, in the grand scheme of things, most people who write code as professionals are not necessarily writing code for themselves, they are developing an application for a user. The end user doesn't care about how readable your code is (you should document confusing code), they just care about getting results and getting them as soon as humanly possible. <grin>
    </soapbox>


    Anyhow, I tend to like the code presented in Test3() myself.


    Exquistite!

    I tend to like the code presented in Test4(), myself.

    Got any other pointless tests we can laugh at?

    Like the soapbox thing, btw. Come down to Hyde Park Corner, some time. I'll be the gent with the carnation in my lapel and a ball peen hammer to take the rest of the world out of your misery.
  • wanze 2008-02-16 21:55
    Why make it harder than it is? If "\n" works, go with it. If it works, don't fix it. Especially not by making it more difficult.
  • Watson 2008-02-16 23:53
    JoeDelekto:
    For anyone that is at all remotely interested in using .NET, Lutz Roeder's Reflector should be the #1 tool in any .NET developer's toolchest.
    Not until it stops it with that "If you don't download the newest version I will refuse to run" idiocy.
  • repeat 2008-02-17 05:06
    JoeDelekto:
    On a momentary tangent, it still surprises me how many people ignore (usually under the guise of "pre-mature optimization" being the root of all evil) the true cost of things.

    In engineering school, the students are usually taught about not just the cost in terms of economic dollars, but in some cases, the amount of energy expended, the number of CPU cycles clicked, etc. In cases of abstraction where a lot of work for developers is now being handled by: a) the framework; and b) the compiler, the developer should still be cognizant of what is going on under the hood, since the abstraction of modern development tools merely shields people from the complexities of various algorithms as well as assists in the generation of boring and boilerplate code.

    For anyone that is at all remotely interested in using .NET, Lutz Roeder's Reflector should be the #1 tool in any .NET developer's toolchest.

    I created four simple C# static methods on the 'Main' object of a console application, using the various string concatenation methods that I've seen discussed here and weighed their cost using various criteria such as instructions used, function calls made, size of code, etc. I invite anyone using Reflector to see my findings as well, make sure you disassemble to "IL" code so you can see what the compiler truly generates.


    static void Test1()
    {
    string test1 = "part1" + Environment.NewLine + "part2" + Environment.NewLine + "part3" + Environment.NewLine;
    }

    static void Test2()
    {
    string newLine = Environment.NewLine;

    string test2 = "part1" + newLine + "part2" + newLine + "part3" + newLine;
    }

    static void Test3()
    {
    string newLine = Environment.NewLine;

    string test3 = String.Concat("part1", newLine, "part2", newLine, "part3", newLine);
    }

    static void Test4()
    {
    string test4 = String.Format("part1{0}part2{0}part3{0}", Environment.NewLine);
    }



    I found, after examining the generated IL of a release build, that Test2 and Test3 generated identical code. That's because using the '+' operator becomes a String.Concat() call. In that regard, using either method in Test2() or Test3() is a matter of coding standards or what might be considered most readable/understandable to the developer.

    Test1(), while also very readable, is highly inefficient, since every instance of Environment.Newline results in a function call to get the newline string for that environment.

    Test4(), by the way, is very readable, looks nice, sweet and compact. However, look at it under the hood with reflector. See that objects are created and constructed, functions called, processing done that's not visible unless one actually looks under the hood. String.Format() does indeed use a StringBuilder under the hood, because it is most efficient when dealing with a homogenous set of values that it might expect to find in a format specifier.

    StringBuilder, btw, is not a stigma, it does have some very good advantages when used to build large strings or strings that are non-deterministic due to logic within the flow of a program as well as being a conduit to marshal string data back and forth between non .NET code.

    <soapbox>

    Anyhow, my point is this: Never jump to conclusions based on readability of the code alone. Readable code is not necessarily the most optimal and premature optimization (which can make less-readable code) is also not necessarily the best path to choose. However, unless a developer is lazy and does not look at all the options to weigh them, they will not find a "happy medium" to choose between the two. Also, one has to understand the platform on which they are writing code. This includes not just your code, but also the operating system and in some cases, the CPU itself.

    Anyhow, in the grand scheme of things, most people who write code as professionals are not necessarily writing code for themselves, they are developing an application for a user. The end user doesn't care about how readable your code is (you should document confusing code), they just care about getting results and getting them as soon as humanly possible. <grin>
    </soapbox>


    Anyhow, I tend to like the code presented in Test3() myself.



    Someone posted this (Grovesy?) on page1, complete with the IL output.

    by the way, you can use ildasm.exe to view the IL output, comes wit the .net framework.
  • Ben Smith 2008-02-17 05:07
    You mean, there's a way other than "\n"? Yeah, I knoes that Windows uses \r\n but PHPGTK works as expected with just \n. Since PHPGTK is the only way I bother writing code that will never run on Windows, this is very much a NON ISSUE.

    Seriously, why don't we programmers have a constant LF like:

    $a="This is some test".LF."This is the next line";

    And let LF be a constant that changes with whatever O/S? So stupid to be worrying about this stuff that was all but resolved in 1976!
  • JiP 2008-02-17 09:50
    Why still bother with newlines? Just get a video card that allows you to put enough monitors next to each other so everything fits on a single line...

    I will lead the way: To start with, I replaced my old 1280x1024 CRT with a 1440x900 LCD screen. Roughly an equal number of pixels, but longer and fewer lines. I have been looking for a 65536x16 pixel screen, but I have been unable to find one yet.

    And as for the line separators used in this comment: Although soon I will no longer need them myself, I have strong hopes that everyone's viewer (even Notepad) will be able to grasp them. Otherwise you'll end up right-scrolling a very long way...
  • Ben 2008-02-17 15:54
    Why is "\n" non-portable? I'm not a .NET guy, but I've used "\n" on DOS/Windows for ages, and whatever's *outputting* the string takes care of it ... if you're outputting to the console or a file in text mode, it'll nicely change it to Newline ("\r\n") for you. If you're outputting to a file in binary mode, it'll output "\n" literally.
  • real_aardvark 2008-02-17 19:43
    Sean:
    sobani:
    Windows has:
    "\r\n"

    Linux has:
    "\n"

    MacOS has:
    "\r"

    That's why you should use the Right Way instead of the Easy Way.


    Nah, that's just the reason OSX and Windows are wrong.

    In the beginning, God created Ken Ritchie.

    The world went predictably downhill after that.
  • JoeDelekto 2008-02-17 19:44
    [quote user="real_aardvark]
    Exquistite!

    I tend to like the code presented in Test4(), myself.

    Got any other pointless tests we can laugh at?

    Like the soapbox thing, btw. Come down to Hyde Park Corner, some time. I'll be the gent with the carnation in my lapel and a ball peen hammer to take the rest of the world out of your misery.[/quote]

    Actually, they weren't tests, they were examinations of what the compiler generated from the different ways to write code. If you aren't one of those people who care how much things cost "under the hood" then, of course, you would find it pointless.

    And as an aside, I believe nobody should take a hammer to their balls, no matter how peen they are. If that's what one expects in Hyde Park Corner, there's a good reason why that corner has been hidden.
  • real_aardvark 2008-02-17 19:45
    Dan Neely:
    shouldn't this constant have been named cpCRLF?

    (cp = C Pound).

    Actually, it should have been named "Ermintrude."

    There are only so many meaningful cases of Hungarian notation to go round.
  • JoeDelekto 2008-02-17 19:52
    Watson:
    JoeDelekto:
    For anyone that is at all remotely interested in using .NET, Lutz Roeder's Reflector should be the #1 tool in any .NET developer's toolchest.
    Not until it stops it with that "If you don't download the newest version I will refuse to run" idiocy.


    I know, it is quite an annoyance, but it is still the best tool I could find that shows what is going on under the hood when something doesn't work as expected.

    To give an example, a person once complained that when they changed the opacity property of their form, dragging it around the screen was slow, but when they set the opacity back to full (after it had already been full), the dragging was still slow.

    After digging into the framework using reflector, I found that there was a 'bug' in which an API call wasn't made to make the window unlayered.

    Over time, it still amazes me how people don't think that either the third party libraries or even the documentation are flawless, because they don't have the skills to investigate it.
  • real_aardvark 2008-02-17 19:56
    JoeDelekto:

    Actually, they weren't tests, they were examinations of what the compiler generated from the different ways to write code. If you aren't one of those people who care how much things cost "under the hood" then, of course, you would find it pointless.

    And as an aside, I believe nobody should take a hammer to their balls, no matter how peen they are. If that's what one expects in Hyde Park Corner, there's a good reason why that corner has been hidden.

    Yes, Hyde Park Corner is well-nigh invisible, and has been ever since the fourth Harry Potter book. Or was it the fifth? I wasn't paying attention; I was too busy looking under the hood.

    I program in C++. I have no problem with people programming in C#. I don't even have a problem with people programming in Java, although I occasionally allow myself the luxury of wondering, "Why?"

    Every now and again, I wonder quite how much CPU might be taken up by a particular loop, or invocation of the OS kernel, or an inadvertent call to the assembly instruction "Halt and catch fire."

    I do not, as a matter of course, trouble my few remaining grey cells by exercising them with the concept of converting EOL into CIL. The poor little buggers are still trying to work out whether Hyde Park Corner disappeared between pages 600 and 650, or perhaps even later.

    On the whole, I prefer to reserve them for more important computational tasks. Like writing code that actually makes some goddamn sense.

    Which, I believe, was my original point.
  • real_aardvark 2008-02-17 19:58
    JoeDelekto:
    Over time, it still amazes me how people don't think that either the third party libraries or even the documentation are flawless, because they don't have the skills to investigate it.

    That would be "think," rather than "don't think."

    An inspiration for us all, I don't think.
  • JoeDelekto 2008-02-17 20:00
    real_aardvark:
    Sean:
    sobani:
    Windows has:
    "\r\n"

    Linux has:
    "\n"

    MacOS has:
    "\r"

    That's why you should use the Right Way instead of the Easy Way.


    Nah, that's just the reason OSX and Windows are wrong.

    In the beginning, God created Ken Ritchie.

    The world went predictably downhill after that.


    I suppose you weren't referring to Brian Kernighan and Dennis Ritchie, those who birthed the 'C' Programming language.
  • JoeDelekto 2008-02-17 20:09
    real_aardvark:
    JoeDelekto:
    Over time, it still amazes me how people don't think that either the third party libraries or even the documentation are flawless, because they don't have the skills to investigate it.

    That would be "think," rather than "don't think."

    An inspiration for us all, I don't think.


    Touche' ...I have expanded it out. "People do not think that either the third party libraries or even the documentation are flawless, because they do not have the skills to investigate it."

    Yep, I made a mistake. The "do not think" and "are flawless" contradict my point. I should have said: "People think, at times, that third party libraries or the documentation are flawless, yet they do not have the skills to investigate it."

    Thank you for the correction.
  • JoeDelekto 2008-02-17 20:20
    real_aardvark:
    JoeDelekto:

    Actually, they weren't tests, they were examinations of what the compiler generated from the different ways to write code. If you aren't one of those people who care how much things cost "under the hood" then, of course, you would find it pointless.

    And as an aside, I believe nobody should take a hammer to their balls, no matter how peen they are. If that's what one expects in Hyde Park Corner, there's a good reason why that corner has been hidden.

    Yes, Hyde Park Corner is well-nigh invisible, and has been ever since the fourth Harry Potter book. Or was it the fifth? I wasn't paying attention; I was too busy looking under the hood.

    I program in C++. I have no problem with people programming in C#. I don't even have a problem with people programming in Java, although I occasionally allow myself the luxury of wondering, "Why?"

    Every now and again, I wonder quite how much CPU might be taken up by a particular loop, or invocation of the OS kernel, or an inadvertent call to the assembly instruction "Halt and catch fire."

    I do not, as a matter of course, trouble my few remaining grey cells by exercising them with the concept of converting EOL into CIL. The poor little buggers are still trying to work out whether Hyde Park Corner disappeared between pages 600 and 650, or perhaps even later.

    On the whole, I prefer to reserve them for more important computational tasks. Like writing code that actually makes some goddamn sense.

    Which, I believe, was my original point.


    Well, I think code that makes 'sense' changes over time. A person who is used to writing console applications gets a bit confused about the whole "event-driven" paradigm when they use a different operating system.

    What used to make 'sense' to me from one realm has changed when I entered the next.

    However, I had, at one point, stopped to do things the way I was used to doing them as a developer and consider the user who was using what I had written. (Writing code for myself was never a problem, writing code for other persons introduced new things.)

    I like to write code that makes sense, however, there are times I have to write code which doesn't. If that is ever the case, I document it thoroughly within comments in the code.
  • real_aardvark 2008-02-17 21:08
    JoeDelekto:
    Thank you for the correction.

    Not at all. Thank you for the Ritchie one.
  • Dutchieman 2008-02-18 01:07
    Actually, in Java, "\n" actually IS a Unicode newline character, which gets translated to the right sequence of bytes (#13, #10, or #13#10) when outputting it through an OutputStream. Strings are always Unicode (2 bytes/char) in Java.

    I'm kinda surprised it doesn't work the same way in .NET...
  • JiP 2008-02-18 06:20
    Never mind the earlier funny remarks about not using newlines altogether:

    I seem to remember MS-DOS (versions 1.xx through 6.xx) was the only OS around at the time somehow needed the redundant CHR(10) (in style, this is GW-BASIC ;-) ) extension to get printers (you know, the old needles-and-pins-things-that-drove-you-crazy-with-their-incredible-noise ones) to output documents correctly.
    Like using a backslash instead of a forward slash as directory separator, I suspect this was done by Microsoft to prevent compatibility between the then-existing OSes and their new kiddy.

    Can anyone confirm this? It's been a long time...
  • Stig Hemmer 2008-02-18 11:31
    For very old printers, CRLF makes sense because you sometimes want to do only CR to print two lines on top of each other, for underlining, bold print and various composed characters. (One could also use BACKSPACE for this)

    You might want to use a naked LF too, though that would be a rarer case. (When writing a narrow column of text down the middle of the paper, without having the print head moving all the way to the margin for each line)

    Since, in the very early days, you didn't want to waste CPU on processing files when printing them, you stored the files with CRLF in them. This meant a file could contain underlining etc. in a way the printer handled directly.

    When Unix was created, they decided that you would always use a device driver of some sort to talk to printers, and that driver could convert things as needed. Given that, it made more sense to use a single character for newline.

    The decided that a lone LF should be converted to CRLF for output, while a lone CR would just be sent through. This way you could still do overprinting like you used to, without having to waste that extra character on lines that didn't need it. However, you lost the possibility of sending naked LFs to the printer, so this was a trade-off.

    MS-DOS came later than UNIX, but UNIX was still a small player in a field with very many players. MS-DOS decided to go with CRLF, which was not uncommon in those days. (I must admit I have no idea how common, I was still a wee lad at the time)

    As for which slash to use as a path separator, there where a lot of different practices for that too. The whole concept of directories and paths were quite new and were being reinvented all over the place with different syntaxes. Again, there were no reason for MS to copy Unix in particular, so they chose backslash as the character least likely to appear in file names.

    Microsoft could have changed this later on, but breaking backwards compatibility is not done lightly.
  • Fred Fnord 2008-02-18 15:07
    Sorry - I don't find %n on that page.
    And it doesn't work either.

    I allways use \n.
    Sooner or later MS will find out, that unix did it right in the first place.
    I don't support notepad - other editors handle \n gracefully on windows.


    The format specifiers which do not correspond to arguments have the following syntax:
    %[flags][width]conversion

    And, later:

    'n' line separator The result is the platform-specific line separator

    Which is to say, since neither flags nor width apply to newline, %n is a platform-specific line separator.

    Not sure why it doesn't work for you.

    -fred
  • [ICR] 2008-02-18 15:14
    "make sure you disassemble to "IL" code so you can see what the compiler truly generates."
    Except, as I've already pointed out, what the compiler generates isn't what gets executed because of JITing. It's perfectly possible for the JITer to chose to inline the property, meaning that Test1 would be better than Test2.
    In my preliminary investigations, it seems that it's not inlined, while all literature suggests it should be :S

    "The end user doesn't care about how readable your code is (you should document confusing code), they just care about getting results and getting them as soon as humanly possible."
    Not true. Depends on the type of consumer. If it's a home user, they care not only that it's fast, but also that it is to a degree stable. If it's a business or power user then they also tend to care that bugs get fixed quickly. Both of these (stability and maintainability) require clear, clean and easy to understand code.
  • Jb 2008-02-18 23:46
    Wow! For a brief moment I thought that this was directed at me... Just convert the '\n' legacy code (that I wrote) to a system compatible equivilent string programmatically and come one that's not so bad is... WHAT?!?!

    Oh yeah, this is thedailywtf.com. Don't prognosticate because the very reason to read this is because it these stories defy all reason and justifiability. Just remember: CD tray as cup holderl CD tray as cup holder...
  • theultramage 2008-02-19 02:26
    I just hope that the people here who keep using '\n' know what they're talking about. The '\n' is a C construct that is LF while in code/memory, and expands to CR, LF or CRLF when written to disk (depending on the platform).

    This code
    fprintf(file, "\r\n"); // must always be Windows newlines!
    will fail spectacularly on Windows, producing CRCRLF once it's written :)
    (I wonder, would it produce CRCR on Apple?)
  • Eric 2008-02-19 13:50
    No for a small number of strings String.Concat is the correct way to do it, it doesn't parse the string for arguments.
  • savar 2008-02-19 14:23
    joe.edwards@imaginuity.com:
    On Windows platforms, "\r\n" == Environment.NewLine. If you know the only platform your software will run on is Windows (e.g. server-side code), then there's no real distinction.


    what other platforms are people running .net on?
  • Mark Brackett 2008-02-19 21:06
    JoeDelekto:
    On a momentary tangent, it still surprises me how many people ignore (usually under the guise of "pre-mature optimization" being the root of all evil) the true cost of things.

    I created four simple C# static methods on the 'Main' object of a console application, using the various string concatenation methods that I've seen discussed here and weighed their cost using various criteria such as instructions used, function calls made, size of code, etc. I invite anyone using Reflector to see my findings as well, make sure you disassemble to "IL" code so you can see what the compiler truly generates.


    Except that IL (being the Intermediate Language), of course, isn't executed. It's basically just a preparsed C# that's quicker to compile by the JITter. If you're not looking at x86 (or x64, or IA-64, etc.) assembly, then you've also missed the "true" cost.

    Oh - and I'd be curious as to what kind of braindead program would have string concats of Environment.NewLine as it's bottleneck. Profile, and then optimize. Anything else is just bound to be wrong.
  • real_aardvark 2008-02-19 21:44
    Jb:
    Wow! For a brief moment I thought that this was directed at me... Just convert the '\n' legacy code (that I wrote) to a system compatible equivilent string programmatically and come one that's not so bad is... WHAT?!?!

    Oh yeah, this is thedailywtf.com. Don't prognosticate because the very reason to read this is because it these stories defy all reason and justifiability. Just remember: CD tray as cup holderl CD tray as cup holder...

    OK, guys, let's do our best not to prognosticate. Remember, it's:

    "To predict or forecast, especially through the application of skill."

    Entirely relevant to the OP, I would say.
  • Cloak 2008-02-21 09:53
    Aaron:
    Grovesy:
    String.Format uses StringBuilder.

    Which is why you should never ever do

    StringBuilder sb = new ...

    ...
    sb.Append(String.Format("hello {0}", someString);

    A second string builder is created.

    Why should you "never ever" do that? Is there a shortage of StringBuilders that nobody has told me about?

    What if you're creating an error report that's 500 lines long and 20 of those lines have a few tokens to replace, like system info and such? Should you replace the entire thing with one string.Format(...) call with 50 parameters? Or are you instead suggesting that we replace the original 20 Format()ed lines with 80 repetitive Append calls?

    The purpose of a StringBuilder is to avoid the exponential performance associated with a pantload of immutable concatenations. So something like:

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 5000; i++)
    {
    sb.Append("Hello, " + "there.")
    }

    is still far, far better than the old

    string s = string.Empty;
    for (int i = 0; i < 5000; i++)
    {
    s = s + "Hello, " + "there.";
    }

    Yes, both ways are stupid in this contrived example, and if you are writing a really tight loop (which most people reading this have probably never had to write), then you might want to start worrying about things like this. But for the vast majority of programmers and programs, the important concept is just to use the mutable StringBuilder rather than creating the same immutable string over and over again through concats. It doesn't really matter if you use a regular old concat or Format() to feed one individual line to the StringBuilder.

    There's a balance to maintain between performance and code readability. Maybe you really need to optimize the hell out of some chunk of string-twiddling code, but maybe you don't, so never say never.


    I have the impression that things are goin this way:

    In fact, CSAML is able to rid itself of every symbol used in old-syntax C#. For example, consider the following old-syntax C# assignment statement:

    A = 5 * (B + 27 * C);

    This statement translates without much fuss into the following chunk of CSAML:

    <ExpressionStatement>
    <Assignment LValue="A">
    <Assignment.Expression>
    <MultiplicationExpression>
    <Multiplication.Multiplier>
    <Literal Type="{x:Type Int32}"
    Value="5" />
    </Multiplication.Multiplier>
    <Multiplication.Multiplicand>
    <AdditionExpression Augend="B">
    <AdditionExpression.Addend>
    <Multiplication.Multiplier>
    <Literal Type="{x:Type Int32}"
    Value="27" />
    </Multiplication.Multiplier>
    <MultiplicationExpression Multiplicand="C"/>
    </AdditionExpression.Addend>
    </AdditionExpression>
    </Multiplication.Multiplicand>
    </MultiplicationExpression>
    </Assignment.Expression>
    </Assignment>
    </ExpressionStatement>


    I first thought that this guy is making a joke but it seems that is bloody serious about it. Look here: http://www.charlespetzold.com/etc/CSAML.html

    Anybody out there who wants to fight against such insaneness? I will stop programming when I will have to write code like that.

    Somebody has to stop M$'s stupidity. What's the future of programming? In the next phase we will also have to put XML in another format like eXtended XML (XXML)? Where is the end? Writing code like

    A + B = C

    should be 20 lines of code (or more) with several hundreds of characers? The guys who promote such code should be shot before they create greater damage!!! Unbelievable!
  • Cloak 2008-02-21 10:19
    Karellen:
    Well, in C and C-derived languages, the correct way is the same as the easy way. It's just:

    myString = "Line1\nLine2\nLine3";

    If this string is written to a file, stream, socket, etc... that has been opened in text mode, "\n" in the string should be converted into the platform's newline sequence. Similarly, when reading, the platform's newline sequence should be converted to a "\n" for the programmer.

    This is why you seek()/fseek() has quirks when working with text-mode files on platform's newline sequence is not a single byte.

    Of course, UNIX makes things easy by requiring that '\n' is a single byte.


    Well, this is not to defend M$: before computers there were typewriters and they had the possibility to Return the Carriage and to Feed a Line. Both were separate "processes" and hence the CRLF instead of a \n. Doesn't make much sense in our days but explains the Why.
  • BrownHornet 2008-02-21 18:12
    Boris:
    Oh please no. How exactly would you program in something like this? I mean with XAML you can create it all in a visual designer, but actual programming functions? To quote one example,
    A = 5 * (B + 27 * C);
    I mean anyone who knows simple algebra would understand this (minus the semicolon in the end maybe). And no one will ever forget what = means (at least in the context of a single programming language). How the heck are you supposed to remember <Assignment.Expression>? And this is a "simple" example.
    Cloak:
    I have the impression that things are goin this way:

    In fact, CSAML is able to rid itself of every symbol used in old-syntax C#. For example, consider the following old-syntax C# assignment statement:

    A = 5 * (B + 27 * C);

    This statement translates without much fuss into the following chunk of CSAML:

    [code snippet removed]

    I first thought that this guy is making a joke but it seems that is bloody serious about it. Look here: http://www.charlespetzold.com/etc/CSAML.html

    Anybody out there who wants to fight against such insaneness? I will stop programming when I will have to write code like that.

    Somebody has to stop M$'s stupidity. What's the future of programming? In the next phase we will also have to put XML in another format like eXtended XML (XXML)? Where is the end? Writing code like

    A + B = C

    should be 20 lines of code (or more) with several hundreds of characers? The guys who promote such code should be shot before they create greater damage!!! Unbelievable!

    Did you guys miss the date at the end of the article?
  • Cloak 2008-02-22 05:24
    What about:

    Environment.Characters.L + Operation.Concatenate + Environment.Characters.i + Operation.Concatenate +
    Environment.Characters.n + Operation.Concatenate +
    Environment.Characters.e + Operation.Concatenate +
    Environment.NewLine


    This must be THE ONLY RIGHT WAY!!!
  • Cloak 2008-02-22 06:56
    RAW:
    It's actually:

    System.getProperty("line.separator")

    but your point is still valid.



    Pleeze sent me teh codez to create a new line
  • cody 2008-03-02 00:54
    Paolo G:
    "codeier"? That would be the comparative of "codey", right? Adjectives ending in -y form the comparative and superlative using -ier and -iest, and so do adjectives ending in -ey. So "codey" -> "codier", "codiest".
  • Erik 2008-03-12 10:34
    Hehe, wonder how the source for Environment.NewLine looks... >:o)
  • Charles Timko 2008-06-30 10:50
    Buddy:
    Actually, I've done similar - maybe not so verbose.

    If you don't know which platform your code will run on, but you absolutely need to be certain that you write a CR/LF pair (or any kind of line termination) because you know what platform will read the file, specifying each character explicitly is the only way.

    In C, I'd use something like this:

    #define CRLF "\x0d\x0a"

    ...

    fprintf(file, "Ghastly weather%s" CRLF, (emphasize)? "!": ".");


    Or you can just do this

    #define CRLF "\r\n"

    So much typing...ahhh, I think I am going to break my fingers!
  • noah 2008-07-18 16:01
    and therein is proof positive of Windows inherent bloat and redundancy.
  • noah 2008-07-18 16:03
    Sean:
    sobani:
    Windows has:
    "\r\n"

    Linux has:
    "\n"

    MacOS has:
    "\r"

    That's why you should use the Right Way instead of the Easy Way.


    Nah, that's just the reason OSX and Windows are wrong.


    Nah, only one of the three is wrong. The bloated and redundant one. OSX and Linux are just different flavours.
  • neminem 2010-12-07 18:09
    fanguad:
    Don't be ridiculous. All space aliens speak English and have American accents.

    I would like to respond to another old thread with a post that nobody will ever see, and mention that Doctor Who^H^HThe Doctor would disagree with you.
  • cindy 2010-12-22 09:01
    find for all kinds of watches and women handbags

    A Lange & Sohne watches
    http://replica038.com/a-lange-sohne-watches.html

    Audemars Piguet watches
    http://replica038.com/audemars-piguet-watches.html

    Ulysse Nardin watches
    http://replica038.com/ulysse-nardin-watches.html

    Vacheron Constantin watches
    http://replica038.com/vacheron-constantin-watches.html