The importance of System.Environment.NewLine

So, let’s pretend you are happily coding along in C#, doing test-driven development, and you get to a method that needs to return a message that spans multiple lines. Say, an address printer that prints out like:

Cory Foy
12345 Developers Way
Columbia, MO 12345

So what is the test you should write? How about:

[Test]
public void printAddressSpansThreeLinesWhenOneAddressLine()
{
  string expected = "Cory Foy\r\n12345 Developers Way\r\nColumbia, MO 12345";
  Assert.AreEqual(expected, customer.printAddress());
}

or maybe:

[Test]
public void printAddressSpansThreeLinesWhenOneAddressLine()
{
  string expected = @"Cory Foy
12345 Developers Way
Columbia, MO 12345";
  Assert.AreEqual(expected, customer.printAddress());
}

The problem is that while both of the above styles are valid C# syntax, they will both fail – on Linux.

“Linux?!”, you gasp!

Yes. There really is quite a push with Mono to get a lot of C# apps running on Linux. The problem is that if you rely on a newline being “\r\n” as it is on Windows, your apps aren’t portable for no other reason then you didn’t know about the difference or didn’t want to bother with it.

The correct solution, which is cross platform and really not that difficult, is:

[Test]
public void printAddressSpansThreeLinesWhenOneAddressLine()
{
  string expected = "Cory Foy" + System.Environment.NewLine
    + "12345 Developers Way" + System.Environment.NewLine
    + "Columbia, MO 12345";
  Assert.AreEqual(expected, customer.printAddress());
}

The same applies for path separators. On Windows, it is “;”. On Linux, it is “:”. And, just like NewLine, Microsoft has a System.IO.Path.PathSeparator. They also have a System.IO.Path.DirectorySeparatorChar for directory structures.

The tools are there, and not terribly difficult to use. Give it a try and help make your app cross-platform.

Comments on this entry are closed.

  • Chris Wheeler March 17, 2006, 12:35 pm

    This is a good point, *if* your customer is asking for cross-platform compatibility and you have a failing test. Otherwise, leaving portability off the story board is a better idea.

  • Cory Foy March 18, 2006, 4:13 pm

    I can’t be positive, but I very rarely have custoemrs who specifically ask for cross-platform compatability.

    But, really this seems to mostly apply in the tests themselves. For example, I’ve spent the past two weeks fixing several classes in the NUnit source tests because they were failing on Mono. And they were only failing because of the very thing mentioned above.

    Sure, when it comes to things like Internationalization, you might want to hold off a bit. But something as easy as replacing your “\r\n”‘s with NewLine calls? Doesn’t seem like such a big deal to me. (Though I am plenty guilty of using “\r\n”)

  • Blair Allen Stark June 17, 2006, 7:23 pm

    just a suggestion,

    the static string.Format can make this a little easier:

    string expected = string.Format(“Cory Foy{0}12345 Developers Way{0)Columbia, MO 12345″, System.Environment.NewLine);

  • Blair Allen Stark June 17, 2006, 7:24 pm

    ack. . . fat fingers:

    string expected = string.Format(“Cory Foy{0}”+
    “12345 Developers Way {0}”+”Columbia, MO 12345″, System.Environment.NewLine);