Problem with multi-line const strings and Environment.Newline

R

rossum

I want to declare a const multi-line string inside a method, and I am
having some problems using Environment.NewLine.

I started out with:

class foo {

public void PrintStuff() {
const string multiline =
"The first line." + Environment.NewLine +
"The second line." + Environment.NewLine +
"The third line.";
Console.WriteLine(multiline);
}

}

Trying to compile this gives me:

"Error 'multiline' is of type 'string.' A const of reference type
other than string can only be initialized with null."

Somewhat confusing, since 'multiline' _is_ of type string so the rest
of the error message does not apply. It does underline the last of
the Environment.NewLine's which is presumably what it is objecting to.
Experimenting with taking them out shows that any Environment.NewLine
will cause a failure to compile, with the last one underlined.

This string is only used inside the method, and is never changed. It
will compile as readonly outside the method, but that makes for
useless clutter at the class level. It will compile as a non-const
string, but that is not as safe as I would like it to be. It will
compile with a hard coded '\n' in the strings, but that is not as
portable as I would want it to be.

How can I declare an unchanging multi-line string inside a method
while still using Environment.NewLine as the line separator?

rossum
 
P

Peter Bradley

I may be old fashioned, but you just can't beat the old "\n", in my view:

class foo {

public void PrintStuff() {
const string multiline =
"The first line." + "\n" +
"The second line." + "\n" +
"The third line.";
Console.WriteLine(multiline);
}
}

It works for me.


Peter
 
B

Bruce Wood

rossum wrote:
How can I declare an unchanging multi-line string inside a method
while still using Environment.NewLine as the line separator?

The short answer: you can't. Environment.NewLine is a property, not a
constant, so using it as part of the declaration of a constant would
involve the compiler having to invoke a run-time property at
compile-time, which it can't do. The C# compiler doesn't generate code
to produce const objects; if it can't compute them at compile time then
it barfs.
 
R

Rad [Visual C# MVP]

Hey,

You can do away with the newlines too. Just do this:

const string multiline =
@"The first line.
The second line.
The third line.";
 
B

Bruce Wood

True, but the OP is looking for portability across platforms.

Using \n and the @ trick aren't portable. Using \n (or \r\n) embeds a
particular newline sequence in the string. The @ trick will (I believe)
embed newlines from the platform on which the code is compiled.

Only Environment.NewLine adapts to the platform on which the code is
run. However, it's not a constant, so you can't use it to define
constants.
 
M

Martin Z

Bruce said:
True, but the OP is looking for portability across platforms.

Using \n and the @ trick aren't portable. Using \n (or \r\n) embeds a
particular newline sequence in the string. The @ trick will (I believe)
embed newlines from the platform on which the code is compiled.

Only Environment.NewLine adapts to the platform on which the code is
run. However, it's not a constant, so you can't use it to define
constants.

Thankyou for that painful bit of information. Now I get to look
forward to converting all my crap over to "Environment.Newline" so that
I can maintain some idiotic ideological connection to the Linux world
in my little opensource hobbyhorse apps.
 
R

Rad [Visual C# MVP]

Chasing cross platform compatibility is harder than it looks, and if
you really want to do it you must think of many other things like file
separators, drive access (or lack thereof), legal and illegal file
names, security etc.

Personally I would not go out of my way to do it.

But if you really really have to do it, you can omit the cost and the
code will compile and run merrily

string multiline =
"The first line." + Environment.NewLine +
"The second line." + Environment.NewLine +
"The third line.";
Console.WriteLine(multiline);
 
R

rossum

I want to declare a const multi-line string inside a method, and I am
having some problems using Environment.NewLine.

I started out with:

class foo {

public void PrintStuff() {
const string multiline =
"The first line." + Environment.NewLine +
"The second line." + Environment.NewLine +
"The third line.";
Console.WriteLine(multiline);
}

}

Trying to compile this gives me:

"Error 'multiline' is of type 'string.' A const of reference type
other than string can only be initialized with null."

Somewhat confusing, since 'multiline' _is_ of type string so the rest
of the error message does not apply. It does underline the last of
the Environment.NewLine's which is presumably what it is objecting to.
Experimenting with taking them out shows that any Environment.NewLine
will cause a failure to compile, with the last one underlined.

This string is only used inside the method, and is never changed. It
will compile as readonly outside the method, but that makes for
useless clutter at the class level. It will compile as a non-const
string, but that is not as safe as I would like it to be. It will
compile with a hard coded '\n' in the strings, but that is not as
portable as I would want it to be.

How can I declare an unchanging multi-line string inside a method
while still using Environment.NewLine as the line separator?

rossum
Thankyou all for your replies. It looks like I am going to have to
settle for a less than ideal solution.

On a minor point, the reason for not wanting '\n' is not for Linux
compatibility, which is not really practicable at the moment, it is
for compatibility with some Windows editors (Notepad etc.) which treat
'\n' as an unknown character and put all the separate lines on one
line with an "unknown character" box where the newline should be.

The actual program is writing to disk and not the console as my small
example did, so I need to be able to edit the output easily.

rossum
 
B

Bruce Wood

Rad said:
Chasing cross platform compatibility is harder than it looks, and if
you really want to do it you must think of many other things like file
separators, drive access (or lack thereof), legal and illegal file
names, security etc.

Yes. You have to make sure that you use System.IO.Path for manipulating
file names, etc.
Personally I would not go out of my way to do it.

I agree. I wonder how many people are really trying to run .NET apps
under Mono,and how many will in the future.

Nonetheless, portability was the OP's stated goal, so....
 
L

Lucian Wischik

rossum said:
On a minor point, the reason for not wanting '\n' is not for Linux
compatibility, which is not really practicable at the moment, it is
for compatibility with some Windows editors (Notepad etc.) which treat
'\n' as an unknown character and put all the separate lines on one
line with an "unknown character" box where the newline should be.

I guess it depends what you mean by "linux compatibility".

I write my cross-platform programs to work equally with \n, \r, \r\n
as line-separators. Emacs and Pico work equally with all of them. And
RFC822 for instance stipulates CRLF as its line-separator, so unix
mail programs are supposed to use \r\n.

I think we're in the age now where files are expected to work on unix
and windows and mac without any CR/LF translations: no one's using FTP
ascii mode anymore to transfer files.
 
J

Jon Skeet [C# MVP]

Lucian Wischik said:
I guess it depends what you mean by "linux compatibility".

I write my cross-platform programs to work equally with \n, \r, \r\n
as line-separators. Emacs and Pico work equally with all of them. And
RFC822 for instance stipulates CRLF as its line-separator, so unix
mail programs are supposed to use \r\n.

I think we're in the age now where files are expected to work on unix
and windows and mac without any CR/LF translations: no one's using FTP
ascii mode anymore to transfer files.

It entirely depends what you're doing. If you're writing a string which
will be displayed in a textbox or a label, I seem to remember that on
Windows with WinForms you *must* use \r\n. I've no idea what Mono does
on that front.

Likewise some network protocols specify one particular line termination
style or another.

I would use Environment.NewLine when writing a plain text file, but for
a lot of the rest of the time it's worth putting a bit of effort into
thinking where exactly the output is going, and whether that format has
a specific line termination requirement.
 
B

Bruce Wood

rossum said:
Thankyou all for your replies. It looks like I am going to have to
settle for a less than ideal solution.

On a minor point, the reason for not wanting '\n' is not for Linux
compatibility, which is not really practicable at the moment, it is
for compatibility with some Windows editors (Notepad etc.) which treat
'\n' as an unknown character and put all the separate lines on one
line with an "unknown character" box where the newline should be.

The actual program is writing to disk and not the console as my small
example did, so I need to be able to edit the output easily.

Have you tried embedding \r\n in the string rather than \n? \r\n is the
standard Windows line termination sequence....
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top