在C#中,字符串前面的@是什么?


602

这是C#(或可能是VB.net)的.NET问题,但我试图找出以下声明之间的区别:

string hello = "hello";

string hello_alias = @"hello";

在控制台上打印输出没有区别,长度属性相同。


请参阅(并投票赞成)我对Visual Studio IDE的建议,以获得更好的逐字字符串格式:缩进多行逐字字符串
奥利维尔·雅各布·德斯科姆斯

需要明确的是,上面的示例使用或不使用都会产生完全相同的结果@
Miro J.

Answers:


767

它将字符串标记为逐字字符串文字 -字符串中通常被解释为转义序列的任何内容都将被忽略。

所以"C:\\Users\\Rich"@"C:\Users\Rich"

有一个例外:双引号需要一个转义序列。要转义双引号,您需要连续放置两个双引号。例如,@""""计算为"


1
@RichardEverett我理解了答案,但我怀疑此功能的实际用途是什么?
阿伦2014年

24
@Arun在处理包含诸如正则表达式定义之类的东西的字符串时,这真的很有用-经常需要自己转义的东西
James Thorpe 2015年

25
+多行内容
Jaider

4
{{如果您想在string.Format通话中使用常规花括号,则还必须将花括号加倍。
Dave Cousineau

4
@RichardEverett对于创建多行字符串文字而不必将行分成几部分非常有用。
约翰·莫特

256

这是逐字字符串文字。这意味着不应用转义。例如:

string verbatim = @"foo\bar";
string regular = "foo\\bar";

在这里verbatimregular具有相同的内容。

它还允许多行内容-对于SQL来说非常方便:

string select = @"
SELECT Foo
FROM Bar
WHERE Name='Baz'";

对于逐字字符串文字而言,转义所需要的一点是获得双引号(“),方法是将其加倍:

string verbatim = @"He said, ""Would you like some coffee?"" and left.";
string regular = "He said, \"Would you like some coffee?\" and left.";

16
它还允许将保留字用作变量名和填充物。像public int GetValueOrDefault(int @default);
Svish

5
Svish:正确,但与该特定问题无关。
乔恩·斯基特

63

“ @”也具有另一种含义:将其放在变量声明的前面,使您可以将保留的关键字用作变量名。

例如:

string @class = "something";
int @object = 1;

我只发现一两个合法用途。当您想执行以下操作时,主要在ASP.NET MVC中:

<%= Html.ActionLink("Text", "Action", "Controller", null, new { @class = "some_css_class" })%>

这将产生一个HTML链接,例如:

<a href="/Controller/Action" class="some_css_class">Text</a>

否则,您将不得不使用“类”,它不是保留关键字,但大写的“ C”不遵循HTML标准,并且看起来不正确。


18

由于您也明确要求使用VB,因此让我补充一下,此逐字字符串语法在VB中不存在,仅在C#中不存在。而是,所有字符串在VB中都是逐字记录的(除了它们不能包含换行符的事实,不同于C#逐字字符串):

Dim path = "C:\My\Path"
Dim message = "She said, ""Hello, beautiful world."""

转义序列在VB中不存在(除了引号字符加倍,例如C#逐字字符串)外,这使某些事情变得更加复杂。例如,要在VB中编写以下代码,您需要使用串联(或其他任何构造字符串的方式)

string x = "Foo\nbar";

在VB中,其编写方式如下:

Dim x = "Foo" & Environment.NewLine & "bar"

&是VB字符串连接运算符。+同样可以使用。)


1
哦,天哪,这很烦人……更高兴的是我现在正在使用C#:p
Svish

您不能将换行符嵌入VB字符串文字中,即使您可以将其插入C#的逐字字符串文字中。因此,它们并不相同。
乔伊,

@Svish,等等我想念什么吗?这根本不是VB的缺点。确实,这是VB赢得C#的地方。最好这样做,并显式地合并换行符和特殊字符,而不是在"和之间插入所有特殊字符"
Pacerier,2015年

@Pacerier废话。一旦完成了琐碎的字符串处理工作,必不可少的是,适当的字符串构建工具必不可少,而精简处理特殊字符的能力是其中最重要的。但是,C#和VB都具有String.Format,因此可以执行此操作。实际上,我现在永远不会"x" & Environment.NewLine,而总是使用String.Format("x{0}", Environment.Newline)etc。不过,这里的C#更方便。
康拉德·鲁道夫

@KonradRudolph,我会选择"x" & nl & nl"x" + nl + nl"x" . $nl . $nl每天结束"x\n\n"。也"x" + bs + bs 结束了"x\\\\"。而"x" + q + q"x\"\""/ "x"""""。现在String.Format,这是与我们上面进行的比较无关的另一个问题。
Pacerier,2015年

10

http://msdn.microsoft.com/zh-CN/library/aa691090.aspx

C#支持两种形式的字符串文字:常规字符串文字和逐字字符串文字。

常规字符串文字由零个或多个用双引号引起来的字符组成,例如“ hello”,并且可以包括简单的转义序列(例如,制表符\ t)以及十六进制和Unicode转义序列。

逐字字符串文字由@字符,后跟双引号字符,零个或多个字符和结束双引号字符组成。一个简单的例子是@“ hello”。在逐字字符串文字中,定界符之间的字符逐字解释,唯一的例外是引号-转义序列。特别是,简单的转义序列以及十六进制和Unicode转义序列不在逐字字符串文字中处理。逐字字符串文字可以跨越多行。


9

这是一个逐字字符串,并更改了转义规则-现在唯一转义的字符是“,转义为”“。这对于文件路径和正则表达式特别有用:

var path = @"c:\some\location";
var tsql = @"SELECT *
            FROM FOO
            WHERE Bar = 1";
var escaped = @"a "" b";

等等


您是不是在示例中缺少@,Marc?还是使用var时的默认设置?
有点

1
好的-真的,真的很奇怪。我想知道编辑是否对它们进行了咀嚼?
马克·格雷夫

9

MSDN复制:

在编译时,将逐字字符串转换为具有所有相同转义序列的普通字符串。因此,如果在调试器监视窗口中查看逐字字符串,则将看到编译器添加的转义字符,而不是源代码中的逐字版本。例如,逐字字符串@"C:\files.txt"将在监视窗口中显示为"C:\\files.txt"


这是Microsoft文档的典型误导性内容,恕我直言!上面所说的最终结果是正确的,但基本的事实是C#中的字符串被转换为相关的字节序列(或多字节字符代码)。C#允许使用两种不同的方式来表示基础字符串,即@“ ...”或“ ...”。调试器始终选择“ ...”方式,并且无法确定最初使用的是哪种方式。(转义序列\ n或“”仅与编程和显示级别的字符串表示形式有关,并且永远不会存储在基础字符串中!)
MikeBeaton

8

将a @放在字符串前面,使您可以使用特殊字符(例如反斜杠或双引号),而不必使用特殊代码或转义字符。

所以你可以这样写:

string path = @"C:\My path\";

代替:

string path = "C:\\My path\\";

3

解释很简单。为了表示字符串"string\",编译器需要使用,"string\\"因为\它是转义字符。如果您@"string\"改用,则可以忽略\\

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.