What is the significance of the # symbol in C sharp? [duplicate] - c#

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What's the # in front of a string for .NET?
I understand using the # symbol is like an escape character for a string.
However, I have the following line as a path to store a file to a mapped network drive:
String location = #"\\192.168.2.10\datastore\\" + id + "\\";
The above works fine but now I would like to get a string from the command line so I have done this:
String location = #args[0] + id + "\\";
The above doesn't work and it seems my slashes aren't ignored. This my command:
MyProgram.exe "\\192.168.2.10\datastore\\"
How can I get the effect of the # symbol back?

It is used for two things:
create "verbatim" strings (ignores the escape character): string path = #"C:\Windows"
escape language keywords to use them as identifiers: string #class = "foo"
In your case you need to do this:
String location = args[0] + id + #"\\";

The # symbol in front of a string literal tells the compiler to ignore and escape sequences in the string (ie things that begin with a slash) and just to create the string "as-is"
It can also be used to create variables whose name is a reserved work. For example:
int #class=10;
If you don't prefix the # then you'd get a compile-time error.
You can also prefix it to variables that are not reserved word:
int #foo=22;
Note that you can refer to the variable as foo or #foo in your code.

The # prefix means the string is a literal string and the processing of escape characters is not performed by the compiler, so:
#"\n"
is not translated to a newline character. Without it, you'd have:
String location = "\\\\192.168.2.10\\datastore\\\\" + id + "\\\\";
which looks a bit messy. The '#' tidies things up a bit. The '#' can only be prefixed to string constants, that is, things inside a pair of double quotes ("). Since it is a compiler directive it is only applied at compile time so the string must be known at compile time, hence,
#some_string_var
doesn't work the way you think. However, since all the '#' does is stop processing of escaped characters by the compiler, a string in a variable already has the escaped character values in it (10,13 for '\n', etc). If you want to convert a '\n' to 10,13 for example at run time you'll need to parse it yourself doing the required substitutions (but I'm sure someone knows a better way).
To get what you want, do:
String location = args[0] + id + "\\";

The # symbol has two uses in C#.
To use a quotes instead of escaping. "\windows" can be represented as #"\windows". "\"John!\"" can be represented #"""John!""".
To escape variable names (for example to use a keyword as a parameter name)
private static void InsertSafe (string item, object #lock)
{
lock (#lock)
{
mylist.Insert(0,item);
}
}

#-quoted string literals start with # and are enclosed in double quotation marks. For example:
#"good morning" // a string literal
The advantage of #-quoting is that escape sequences are not processed, which makes it easy to write, for example, a fully qualified file name:
#"c:\Docs\Source\a.txt" // rather than "c:\\Docs\\Source\\a.txt"
To include a double quotation mark in an #-quoted string, double it:
#"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.
Another use of the # symbol is to use referenced (/reference) identifiers that happen to be C# keywords. For more information, see 2.4.2 Identifiers.
http://msdn.microsoft.com/en-us/library/362314fe(v=vs.71).aspx

In this case you may not need to use #; just make it
String location = args[0] + id + "\\";

The # symbol is only relevant for string literals in code. Variables should never modify the contents of a string.

The # symbol goes right before the quotes. It only works on string literals, and it simply changes the way the string is understood by the compiler. The main thing it does is cause \ to be interpreted as a literal backslash, rather than escaping the next character. So you want:
String location = args[0] + id + #"\\";

By default the '\' character is an escape character for strings in C#. That means that if you want to have a backslash in your string you need two slashes the first to escape the second as follows:
string escaped = "This is a backslash \\";
//The value of escaped is - This is a backslash \
An easier example to follow is with the use of quotes:
string escaped = "To put a \" in a string you need to escape it";
//The value of escaped is - To put a " in a string you need to escape it
The # symbol is the equivalent of "ignore all escape characters in this string" and declare it verbatim. Without it your first declaration would look like this:
"\\\\192.168.2.10\\datastore\\\\" + id + "\\";
Note that you already didn't have the # on your second string, so that string hasn't changed and still only contains a single backslash.
You only need to use the # symbol when you are declaring strings. Since your argument is already declared it is not needed. So your new line can be:
String location = args[0] + id + "\\";
or
String location = args[0] + id + #"\";

If you load from the command line, it will already be escaped for you. This is why your escapes are "ignored" from your perspective. Note that the same is true when you load from config, so don't do this:
<add key="pathToFile" value="C:\\myDirectory\\myFile.txt"/>
If you do, you end up with double strings, as ".NET" is smart enough to escape thins for you when you load them in this manner.

Related

Properly escape filepaths

How do I escape with the #-sign when using variables?
File.Delete(#"c:\test"); // WORKS!
File.Delete(#path); // doesn't work :(
File.Delete(#"c:\test"+path); // WORKS
Anyone have any idea? It's the 2nd example I want to use!
Strings prefixed with # character are called verbatim string literals (whose contents do not need to be escaped).
Therefore, you can only use # with string literals, not string variables.
So, just File.Delete(path); will do, after you assign the path in advance of course (from a verbatim string or some other string).
Verbatim strings are just a syntactic nicety to be able to type strings containing backslashes (paths, regexes) easier. The declarations
string path = "C:\\test";
string path = #"C:\test";
are completely identical in their result. Both result in a string containing C:\test. Note that either option is just needed because the C# language treats \ in strings as special.
The # is not some magic pixie dust needed to make paths work properly, it has a defined meaning when prefixed to strings, in that the strings are interpreted without the usual \ escape sequences.
The reason your second example doesn't work like you expect is that # prefixed to a variable name does something different: It allows you to use reserved keywords as identifiers, so that you could use #class as an identifier, for example. For identifiers that don't clash with keywords the result is the same as without.
If you have a string variable containing a path, then you can usually assume that there is no escaping needed at all. After all it already is in a string. The things I mentioned above are needed to get text from source code correctly through the compiler into a string at runtime, because the compiler has different ideas. The string itself is just data that's always represented the same.
This still means that you have to initialise the string in a way that backslashes survive. If you read it from somewhere no special treatment should be necessary, if you have it as a constant string somewhere else in the code, then again, one of the options at the top has to be used.
string path = #"c:\test";
File.Delete(path);
This will work only on a string. The "real" string is "c:\\test".
Read more here.
There's a major problem with your understanding of the # indicator.
#"whatever string" is a literal string specifier verbatim string literal. What it does is tells the C# compiler to not look for escape sequences. Normally, "\" is an escape sequence in a string, and you can do things like "\n" to indicate a new line or "\t" to indicate a tab. However, if you have #"\n", it tells the compiler "no, I really want to treat the backslash as a backslash character, not an escape sequence."
If you don't like literal mode, the way to do it is to use "\\" anywhere you want a single backslash, because the compiler knows to treat an escaped backslash as the single character.
In either case, #"\n" and "\\n" will produce a 2-character string in memory, with the characters '\' and 'n'. It doesn't matter which way you get there; both are ways of telling the compiler you want those two characters.
In light of this, #path makes no sense, because you don't have any literal characters - just a variable. By the time you have the variable, you already have the characters you want in memory. It does compile ok, as explained by Joey, but it's not logically what you're looking for.
If you're looking for a way to get rid of occurrences of \\ within a variable, you simply want String.Replace:
string ugly = #"C:\\foo";
ugly = ugly.Replace(#"\\", #"\");
First and third are actual paths hence would work.
Second would not even compile and would work if
string path = #"c:\test";
File.Delete(path);

C# Settings with verbatim string literal

Perhaps I didn't see or understand any of the answers I read but I am having trouble using verbatim string literal (#) with settings.Default.(mysetting). I am trying to do something like
Directory.GetFiles(#Setting.Default.(mysetting),"*.txt");
and cant seem to find the right syntax to make this work.
The # identifies a string constant literal where back slashes should not be interpreted as escape signs. You can not use it in front of method invocations as you attempt here.
A valid assignment might be
string path = #"c:\temp\example.txt";
Usually a \t would be interpreted as a tabulation character thus making the file reference illegal. It is exactly identical to
string path = "c:\\temp\\example.txt" ;
But bit easier to read.
# verbatim string is used with string literals. So your code should be:
Directory.GetFiles(Setting.Default.(mysetting),#"*.txt");
because "*.txt" is the string literal in your code.
(Although not related, but you can use # with variable names see C# Variable Naming and the # Symbol)
To use # as part of a verbatim string literal, the string literal must be right there - not just a property, method, etc. that returns a string.
string myStr = #"I'm verbatim, I contain a literal \n";
string myStr2 = "I'm not\nI have a newline";
string myStr3 = #myStr2; // still contains a newline, not a literal "\n"
Using # in front of an identifier allows you to use reserved keywords as identifiers. For example:
string #if = "hello!"; // valid
It also works on non-reserved words, where it has no real effect.
string #myVar = "hello!"; // valid
string newVar = myVar; // can be referred to either way
Unless I'm missing it, you still need to wrap the string within quotation marks.

New Line in Constant error when trying to insert escape character in string

I am writing some C# code in which I am fetching values from the database and using it. The problem I am facing is as below.
If my fetched value from the database is:
string cat1 = "sotheby's";
Now while using cat1 I want to insert an escape character before the single quote. To achieve this I have written the below code:
string cat1 = "sotheby's";
if (cat1.Contains("'")) {
var indexofquote = cat1.IndexOf("'");
cat1.Insert(indexofquote-1,"\");
var cat2 = cat1;
}
The error arises on the insert line with the backslash (escape character). The error is New Line in Constant.
Please help me correct this error.
You can't just write "\" in C# code. That will produce the "New Line in Constant" error because it 'escapes' the second quote so that it doesn't count. And the string isn't closed.
Use either "\\" (escaping the \ with itself)
or use #"\" (a verbatim string).
The Backslash in string literals is an escape character, so it must either be escaped itself:
"\\"
Or you can use a so-called verbatim string literal:
#"\"
See: http://msdn.microsoft.com/en-us/library/aa691090.aspx
Regarding your compile error: The backslash escapes the following quotation mark, thus the string literal is not recognized as closed. The following characters ) and ; are valid for string literals, however the line ending (newline) is not. Hence the error.
That will only replace 1 single quote.
To get them all use:
string cat1_escaped = cat1.Replace("'", "\'");
Although a lot of databases don't escape quotes like that, but rather by doubling them:
string cat1_escaped = cat1.Replace("'", "''");

Concatenate string literals with DirectoryInfo enumeration and adding quotation marks.

This seems like such an obscure question, but here it goes:
Is there a way to concatenate String Literals with a DirectoryInfo enumeration (which contains a file path) while adding quotations around the file path? Further, how can I prevent backslashes from being doubled when converting a DirectoryInfo enumeration to a string? My situation is as follows:
DirectoryInfo filePathDirectory = new DirectoryInfo(filePath);
Process a = new Process();
a.StartInfo.FileName = "C:\\Windows\\system32\\lpr.exe";
a.StartInfo.Arguments = "-SServername.Domain.net -Plp " + "\"" + filePathDirectory + "\"";
a.StartInfo.UseShellExecute = false;
a.Start();
a.WaitForExit();
filePathDirectory starts with a value of:
{\\ServerName\Share\Folder\Folder\FileName.xls}
Which I think is converted into a string once concatenated into a.StartInfo.Arguments which is assigned the value of:
-SServername.Domain.net -Plp \"\\\\ServerName\\Share\\Folder\\Folder\\FileName.xls\"
This is bad because, the number of backslashes in the path doubled. How can I ensure no backslashes are added to the path?
On top of that, to add a quotation marks, I've used the backslash escape sequence; But the backslash from this escape sequence is inadvertently added to my string. How can I add quotation marks around the file path which is contained in a.StartInfo.Arguments?
P.S. I hope this makes sense, please ask questions if you need clarification.
The backslashes are not doubled and the backslash of the quotes also "isn't there". You can verify it by Console.WriteLine(a.StartInfo.Arguments) or MessageBox.Show(a.StartInfo.Arguments).
What you are seeing - in the debugger I assume - is the representation of the string with the escape characters not translated - just as you would need to enter it in the IDE.
Example:
string s = "\"";
This will show in the debugger as "\"" but it will display on screen as ":

C# file gettext-string regex parser

SHORT QUESTION
Let's have a regex, which reads a string inside a double quotes. This string is valid only if it has NO double quotes inside.
("([^"]+)")
How would one write a regex, which would have the same functionality but will also work for a string with a double quotes WITH a preceding slash?
"Valid string" //VALID
"Valid \"string\"" //VALID
"Invalid " + "string" //INVALID
"Invalid " + "\"string\"" //INVALID
LONG QUESTION
I'm building my own gettext implementation - I found out that the official gettext apps ( http://www.gnu.org/s/gettext/ ) are not sufficient to my needs.
That means I need to find all strings inside each C# code file myself, but only those which are passed to a particular function as the only parameter.
I built a regex which gets most of the strings. The function Translate is public, static and is situated in the namespace GetTextLocalization and in the class Localization.
(GetTextLocalization\.)?(Localization\.Translate)\("([^"]+)"\)
Of course, this will ONLY find the strings alone and it won't find any strings with a verbatim character. If a string parameter is being passed as an operation ("string a" + "string b") or starts with a verbatim (#"Verbatim string"), it will not parse, but that is not the problem.
The regex definition:
([^"]+)
says that there must be no double quotes inside the string and I know that noone in the company is connecting the string somehow while passing it in the parameter. Still, I need to have this construction as a safety "what if" measure.
But that also causes the problem. The double quotes actually can be there.
Localization.Translate("Perfectly valid String with \"double quotes\"")
I need to change the regex so it will include the strings with a double quote (so I skip anything like Translate("a" + "b") which would mess with the translation catalog) but only those which are preceded by a slash .
I thought I might need to use this (?!) grouping construct somehow but I have no idea where to place it.
Since you probably want to allow doubled backslashes before a quote, I suggest
"(?:\\.|[^"\\])*"
Explanation:
" # Match "
(?: # Either match
\\. # an escaped character
| # or
[^"\\] # any character except " or \
)* # any number of times.
" # Match "
This matches "hello", "hello\"there" or "hello\\" but fails on "hello" there" or "hello\\" there".

Categories