- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Honestly, I want one of those jobs where you get paid for each line of code as well... :-(
Admin
"//The way everyone does it."
Yeah, there's a reason EVERYONE DOES IT this way.
I love it!
Admin
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).
Admin
"//The way everyone does it."
Admin
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.
Admin
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.
Admin
when a vb developer meets .net, coming through the rye..
Admin
The real WTF is not using a StringBuilder!
Admin
Windows has: "\r\n"
Linux has: "\n"
MacOS has: "\r"
That's why you should use the Right Way instead of the Easy Way.
Admin
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.
Admin
At the very least I want to see a NewLineProvider. Plus it's not culture-neutral.
Admin
No
myString = string.Format("Line1{0}Line2{0}Line3", Environment.NewLine);
is the correct way to do it.
Admin
Admin
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.
Admin
The real WTF is .NET. Seriously, how can using an eighteen-letter character combination instead of a two letter one be "the Right Way?".
Admin
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; } } ...
Admin
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
Admin
Admin
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 :-/
Admin
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.
Admin
Don't be ridiculous. All space aliens speak English and have American accents.
Admin
As the compiler will resolve
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
Admin
Wow! I didn't even know Environment.NewLine existed until I read this article. I've always been using \n.
Admin
I've actually seen some .NET books teach using /n as the way to generate a new line instead of the "correct way."
Admin
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.
Admin
I hope you mean "\n" not "/n" !?
Admin
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.
Admin
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...
Admin
Just realised that shortly have hitting post.. :)
Anyhow, checking .net documentation... It is a Constant according to MSDN.
Admin
...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?
Admin
Admin
It's not a constant, it's even a property.
Admin
DEFINE \n Environment.NewLine
Admin
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+
+Environment.NewLine++Environment.NewLine+That might have been as funny as him casting a char to convert into a string on multiple lines...Admin
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)? "!": ".");
Admin
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.
Admin
No, it's C#... VB has vbCrLf.
Admin
There is extra credit for giving VMS end of line code. (hint, none of the above.)
Admin
It completely blows away any benefits you might see from a StringBuilder. It's >10x faster, and much clearer.
Admin
It looks like that is the way .net is going. Anyone seen this :http://www.charlespetzold.com/etc/CSAML.html
Admin
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:
is still far, far better than the old
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.
Admin
i dont
Admin
[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
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
Admin
"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.
Admin
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.
If this value is used in multiple places, THEN of course it makes sense to declare it as a class variable or global.
Admin
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.
Admin
More like:
Well, that would be a good thing if you wanted to run the same program on different platforms without recompiling.
Admin
Admin
I've seen where newlines needed to be coded /r/n btw hence the Environment.Newline
Admin
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 :)