You want to add a newline to a string in your program, and you want to choose between using the string "\r\n" and Environment.NewLine, or something else. What are the differences between these options? Does it matter which one you use?
Here I will outline the different code you could use to accomplish the same thing (add a new line or line break). As I will show, the difference between these is zero in almost all deployment environments. First, let's look at how you can add newlines.
With Environment.NewLine. The following code example shows how you can use Environment.NewLine to make a two-line string with the NewLine constant. The comment in the code shows what the text would look like when viewed.
string something = "First line" +
Environment.NewLine +
"Second line";
// First line
// Second line
string somethingElse = something +
Environment.NewLine +
"Second line";
// First line
// Second line
// Second lineWith "\r\n". In Windows, you need both a carriage return and a newline to break a line. The following example will function exactly as the previous one, and in the next section I will show why.
string other = "First line" +
"\r\n" +
"Second line";
// (Same results as above.)
string otherElse = other +
"\r\n" +
"Second line";
// (Same as previous example.)I used Reflector to inspect the IL (intermediate language) of the two examples above. What I found is that with the .NET Framework 3.5 SP1, Environment.NewLine is simply a property that returns "\r\n." What follows is the above code (in a constructor) in IL.
.method private hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 3
.locals init (
[0] string something,
[1] string other)
L_0000: ldarg.0
L_0001: call instance void [mscorlib]System.Object::.ctor()
L_0006: ldstr "First line"
L_000b: call string [mscorlib]System.Environment::get_NewLine()
L_0010: ldstr "Second line"
L_0015: call string [mscorlib]System.String::Concat(string, string, string)
L_001a: stloc.0
L_001b: ldloc.0
L_001c: call string [mscorlib]System.Environment::get_NewLine()
L_0021: ldstr "Second line"
L_0026: call string [mscorlib]System.String::Concat(string, string, string)
L_002b: pop
L_002c: ldstr "First line\r\nSecond line"
L_0031: stloc.1
L_0032: ldloc.1
L_0033: ldstr "\r\nSecond line"
L_0038: call string [mscorlib]System.String::Concat(string, string)
L_003d: pop
L_003e: ret
}get_NewLine() is used. This style of method call is how property lookups appear in intermediate language. You will see in the above code that in the latter part, the \r\n is embedded, but in the first part, get_NewLine() is called. Here's the definition of get_NewLine().
.method public hidebysig specialname static string get_NewLine() cil managed
{
.maxstack 8
L_0000: ldstr "\r\n"
L_0005: ret
}On Linux (with Mono), Environment.NewLine *may* evaluate to simply "\n" (although for compatibility it might be better to use "\r\n" there too). So which should you prefer? I prefer Environment.NewLine, because it is easier for me to read. Your opinion here might be different. Let me end with a really 'nerdy' point.
Not exactly the same. Besides possibly being equal to a different value on Linux, Environment.NewLine simplifies the handling of string Intern pools. What C# and .NET can do is put all constant strings in your program in a big string intern table.
String intern difference. In the examples, "Second Line" would be interned by C#, but in the latter, "\r\nSecond Line" would be interned. Thus using Environment.NewLine may change (possibly improve) performance of the intern table.