Pet Peeve #493: Console.WriteLine (“n”)


I know, I know, I am an incredible nit picker, but it gives me the willies to see the hard-coded string “\n” used for newline.  It works and there is no real “correctness” argument to be made here, but I just don’t like it.  Here are my reasons:

1. Not self documenting, the “new-guy” (or gal) may not know that “\n” means new line

2. It is unduly concrete  rather than symbolic, making it hard for other software to reason of over the code.

3. Does not work across platforms.   

 

Instead of

        Console.WriteLine(“\n” + name);

 

My suggested alternative is:

        Console.WriteLine();

        Console.WriteLine(name);

Or, if you must have it in one line,

        Console.WriteLine(Environment.NewLine + name);

 

Now, aren’t those much better?

Comments (46)

  1. I’ve been known to do the following when calling StringBuilder.AppendFormat(), which doesn’t have a method that writes a new line. I suppose that it could work for stream output as well, although I’ve never used it that way.

    StringBuilder builder = new StringBuilder(1024);

    string nl = Environment.NewLine;

    builder.AppendFormat("{0}{1}{0}", nl, name);

    The last time that I can recall doing this was when building POST data for an HttpWebRequest. It’s not all that useful for outputting one line, but for several, it’s a real keystroke-saver. Now that we have code snippets, I think I may create one with a shortcut of "nl" or "n" that expands to Environment.NewLine. I wonder if using "n" as the shortcut would cause any problems.

    By the way, it seems that an AppendLine() method has been added in Whidbey, but no AppendLineFormat(). It seems that AppendLine() simply calls Append(Environment.NewLine), so it’s nothing all that special (except for saving a line of code).

    On the surface you would think that I could call String.Format() and pass it to AppendLine(), but that method creates ANOTHER StringBuilder, calls AppendFormat() on it, and returns the string. That hardly seems as efficient.

  2. Jeff Perrin says:

    Heh. That’s funny. I do exactly that, even though I’ll use other framework constants like the path separator. I’m not sure where I picked up the habit, but I haven’t ever even thought of using anything other than n. I even know that there’s a constant for newlines. Doh.

  3. Jerry Pisk says:

    Would you actually hire a new guy (or gal) who doesn’t know such basic escape sequence as n? That would explain a lot about Microsoft’s SW :) The other arguments are fine but this one really cracked me up 😉

  4. Robert says:

    What do you mean "not self documenting?" You can look up the valid escape sequences in the documentation and there it is!

    And, why wouldn’t it be portable to any platform that implements .NET? The character escapes are part of the spec.

  5. Yuri Schimke says:

    This is a lack of Refactoring Tool support.

    With advanced enough tools you can find all String literals, check for contains "n", and replace with Environment.NewLine.

    Tools for Java are advanced enough to allow this, they just don’t expose it currently :)

    No one will complain if you clean up their code and fix this. So if its your project or have commit rights, make the changes, and check them in.

  6. Uwe says:

    Now, hopefully this doesn’t remind me of this one ;-): http://thedailywtf.com/archive/2004/07/23/676.aspx

  7. Jeez, I’ve been reading your blog from pretty much the start, but I’ve seem to have missed the first 492 pet peeves…;)

  8. I thought that n was /defined/ as being the platform’s newline character sequence?

    It’s therefore cross-platform as it stands.

  9. 仪表 says:

    It’s only work in win?

    Console.WriteLine("x0ax0d" + name);

  10. adam says:

    2 things spring to mind, though mainly from a devils advocate point of view.

    1. If the code maintainer does not know what "n" means, what are they doing with my code!

    3. I don’t know about most people but I have only ever written code for Windows, "rn" == CRLF.

  11. Iain says:

    I’m sorry, I think you’re out of your tree with this one.

    1. That’s possible, but I think it’s silly. By the same token, we must avoid CDATA sections in xml, never use c#’s @"" syntax, and refuse to put javascript in asp.net pages, beyond that entered by the platform.

    At a certain point, you have to just say "this is assumed knowledge". n is one of the things that I think it’s perfectly reasonable to assume.

    2. This implies a complete inversion of Postel’s law – tools accepting only a subset of the language. n is part of the language, and tools that claim to speak the language should do so.

    3. Eh? Which platforms doesn’t it work for? In C you just say n and the library makes sure it gets turned into the platform’s newline character, unless you turn off the translation by opening the file in binary mode. There’s no particular reason why that sort of machinery wouldn’t kick in for multi-platform stuff.

    I can state from experience that n does produce a newline under mono on linux.

  12. Anyone says:

    <br>rn ?

  13. a. says:

    if you do not know what is n (t, r) you shouldn’t do programming.

  14. AT says:

    All your suggestions are weak !
    <br>You are solving wrong problem.
    <br>I do not realy care about .NET on UNIX, I care more about performance on my platform I’ve paid money already.
    <br>
    <br>a)
    <br>Console.WriteLine();
    <br>Console.WriteLine(name);
    <br>This will asquere lock on console or stdout file twice ! A lot of useless code will be executed twice to output a few lines
    <br>
    <br>b)
    <br>Console.WriteLine(Environment.NewLine + name);
    <br>This will create new useless object as result of &quot;+&quot; operator and only then will output it !
    <br>
    <br>Both is wrong. There is no way to output series of strings/data without creation of new object with all data or without useless locking of console output.
    <br>
    <br>There is no buffering performed for console output !
    <br>
    <br>Two calls for
    <br>&quot;Console.Write(x);
    <br>Console.WriteLine(y);&quot;
    <br>will take as much as twice more time that single call there z = x+y
    <br>&quot;Console.WriteLine(z);&quot;
    <br>Perform simple testing and compare results (redirection preffered).
    <br>Mine are :
    <br>With file rediction 00:00:00.6409216 vs. 00:00:01.0715408
    <br>Without redirection, console slowed down everything 00:00:11.0759264 vs. 00:00:12.1374528
    <br>
    <br>This is clear that single call to Console.WriteLine is faster, but creation of &quot;x+y&quot;object has additional costs !!
    <br>
    <br>Summary: System.Console must have a way to output series of data in single call.
    <br>Plz do not propose to use &quot;{0}{1}&quot; format. It’s also slow.

  15. compare:

    string text = "The FirstnSecondnThirdnFourth Line";

    to

    string text = "The First" + Environment.NewLine + "Second" + Environment.NewLine + "Third" + Environment.NewLine + "Fourth Line";

    The developers of C wisely included a shorthand for newlines and other control characters. The sad part was, MS ignored the widely accepted use of "n" for new line, and used two characters, instead of one. So now, 24-plus years later, we are still talking about things like Environment.NewLine.

    Anyone familiar with C will understand "n" just fine.

  16. Anonymous says:

    If you do not understand what n is, you shouldn’t be messing around with code. Why make your code slower just to accomidate people who have no business working with it anyway? It’s not a significant performance hit, but if things like this were done throughout the code of a big project, it could make a difference.

  17. Yup that’s more readable. But anyone who has been working wih C, C++ knows n means a new line. LOL

  18. Nils Jonsson says:

    I’m in the choir.

  19. Steve says:

    Honestly… .NET is great, but I don’t see MS ever really putting a focus on being cross-platform.

  20. But does your peeve extend to embedded newlines?

    String.Format(" Name: {0}n Addr: {1}nPhone: {2}", name, addr, phone);

  21. David,
    <br>
    <br>Pet peeve #492 was ‘Typos in Blog Titles’. I missed the first 491 too.

  22. Mi idiot comment of the day: If it’s shorter, it’s gotta be faster. "n" rules.

  23. Sergio Pereira says:

    My idiot comment of the day: If it’s shorter, it’s gotta be faster. &quot;n&quot; rules.

  24. Daniel says:

    Funny thing that a microsoft employee cares about different platforms.

  25. Chris Staley says:

    I think n was one of the first things I learned in CS 101: An Introduction to Programming. Seriously.

  26. Chris Staley says:

    I think n was one of the first things I learned in CS 101: An Introduction to Programming. Seriously.

  27. Chris Staley says:

    I think n was one of the first things I learned in CS 101: An Introduction to Programming. Seriously.

  28. Mehran Nikoo says:

    My question is if ‘n’ is not good enough, then what about the other escape characters? I love being able to use string.Format to use a compact form for concatenating and formatting strings. I don’t like to concatenate strings by closing and opening quotations, which makes the code harder to read in many cases.

  29. Haacked says:

    Correct me if I’m wrong, but I think Brad’s point is that n is often used on Windows when in actuality, the developer probably intended rn (or in demical ASCII code: 13 10).

    In VB, this is known as vbCrLf.

    Environment.NewLine (on Windows) for example is NOT equivalent to n. It’s actually rn.

    Whereas I assume that on Linux (via Mono) Environment.NewLine is equivalent to n (correct me if I’m wrong).

  30. I saw an interesting comment

    "If you do not understand what n is, you shouldn’t be messing around with code. Why make your code slower just to accomidate people who have no business working with it anyway? It’s not a significant performance hit, but if things like this were done throughout the code of a big project, it could make a difference. "

    But the method Brad shows us has no performance issue. Console.WriteLine(Environment.NewLine + name); will run as same as the Console.WriteLine("n" + name). But calling Console.WriteLine twice could have insignificant cost since the function call causes the stack frame allocation, backup the current stack frame and so on.

    What do you think Brad?

  31. Brad Abrams says:

    Well, it sure has been a while sense nearly everyone disagrees with me on an issue… I guess that is why this is a pet peeve and not a design guideline. 😉 Can I assume the “silent masses” are with me? Anyway, take it or leave it.

    On the perf angle, I would be shocked if anyone had a real world scenario for one method being better than the other at least for Console output. String formatting may be a different issue as there is less overhead there, but as Rico would say: “Measure”.

  32. Well there is a difference between n and Environment.NewLine. Try opening a file in Notepad that used only n and not rn… it sucks.

  33. sbjorg says:

    Why is NewLine part of Environment? Why isn’t it part of TextWriter? That way I could open a fresh stream with the intended encoding and then just use it. Thus, the right code would like this:

    Console.WriteLine(Console.Out.NewLine + name);

    Thus, if standard-output has been redirected to a unix/mac device, you’ll get the correct NewLine encoding (or at least, you’d have a chance of getting it).

  34. Brad Abrams says:

    We talked about putting NewLine somewhere in IO, but there is no good place… sometimes you need this when jut building up a string with StringBuilder for example, so it seemed odd to put in in the IO namespace

  35. What about "Console.WriteLine("{0}{1}", Environment.NewLine, name);"?

  36. William Robertson says:

    I used to agree with you to never use "n" with streams, but had an issue using StreamWriter.WriteLine() method. I was creating CSV files by looping through a DataTable. Occasionally, I am guessing, the WriteLine() method was not perfoming as I would expect. IOW no NewLine character was getting put out; two lines of CSV data were being listed as one line.

    I could find no reason for this, and it seems to happen at purely random intervals. I changed all my _Writer.WriteLine() methods over to _Writer.Write( "n" ) and haven’t experienced a problem since.

    If you have a solution for my problem I will be more than happy to switch my code back, since it isn’t as pretty.

  37. John Schroedl says:

    Yes, you approach is more readable. I much prefer Environment.NewLine.

  38. FxCop rule that checks for hard coded new line characters (‘n’ or ‘r’).

  39. FxCop rule that checks for hard coded new line characters (‘n’ or ‘r’).