• loh (unregistered) in reply to Rick

    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 (unregistered) in reply to loh

    My company still develops a product that runs on VMS and our customers continue to purchase new Vax/VMX platforms.

  • Karellen (unregistered)

    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 (unregistered)

    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 (unregistered)

    "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] (unregistered)

    "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 (unregistered) in reply to Martin

    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] (unregistered)

    [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 (unregistered)

    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.

  • (cs) in reply to DOA
    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 (unregistered)

    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 (unregistered)

    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 (unregistered) in reply to WhiskeyJack
    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.

  • (cs) in reply to Martin
    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! (unregistered) in reply to Jim
    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 :-/

  • (cs) in reply to WhiskeyJack
    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 (unregistered) in reply to sobani

    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 (unregistered) in reply to Aaron

    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 (unregistered) in reply to Carra

    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 (unregistered) in reply to Grovesy
    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 (unregistered) in reply to Barf 4 Eva
    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 (unregistered) in reply to joe.edwards
    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 (unregistered) in reply to kobayashi

    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 (unregistered)

    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 (unregistered)

    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 (unregistered) in reply to Aaron
    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 (unregistered) in reply to fanguad

    [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 (unregistered) in reply to Jim

    It's actually:

    System.getProperty("line.separator")

    but your point is still valid.

  • Jim (unregistered) in reply to Aaargh!
    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 (unregistered) in reply to RAW
    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 (unregistered)

    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 (unregistered) in reply to MadQ
    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.

  • (cs) in reply to Jim
    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");

  • (cs)

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

  • (cs) in reply to Mach58
    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 (unregistered) in reply to sobani
    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! (unregistered) in reply to Jim
    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 (unregistered) in reply to Jay
    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 (unregistered)

    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.

  • (cs) in reply to Grovesy

    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 (unregistered) in reply to Jay

    http://en.wikipedia.org/wiki/Newline#History

  • mokus (unregistered) in reply to Mythokia
    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 (unregistered) in reply to Gimpy
    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 ;)

  • (cs) in reply to John
    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. (unregistered) in reply to VGR
    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 (unregistered) in reply to Anonymous
    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 (unregistered) in reply to mokus

    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.

  • (cs) in reply to Carra

    Even String.Format() would have been an improvement.

  • (cs) in reply to MadQ
    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 (unregistered) in reply to Aaron
    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?

Leave a comment on “His Own Way to Newline”

Log In or post as a guest

Replying to comment #:

« Return to Article