ChatGPT解决这个技术问题 Extra ChatGPT

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

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

string hello = "hello";

对比

string hello_alias = @"hello";

在控制台上打印出来没有区别,长度属性是一样的。

请参阅(并赞成)我对 Visual Studio IDE 的建议,以获得更好的逐字字符串格式:Indent multi-line verbatim strings
需要明确的是,上面的示例无论是否使用 @ 都会产生完全相同的结果。

R
Richard Ev

它将字符串标记为 verbatim string literal - 字符串中通常被解释为 escape sequence 的任何内容都将被忽略。

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

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


@RichardEverett 我明白了答案,但我怀疑这个功能的实际用途是什么?
@Arun 在处理包含诸如正则表达式定义之类的字符串时非常有用,这些字符串通常需要自己转义
多行内容
如果您想在 string.Format 调用中使用常规大括号,您还必须将大括号 {{ 加倍。
@RichardEverett 它对于创建多行字符串文字非常有用,而不必将行分成几部分。
l
l'L'l

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

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.";

它还允许使用保留字作为变量名和东西。像 public int GetValueOrDefault(int @default);
Svish:没错,但与这个特定问题无关。
J
JulianR

'@' 还有另一个含义:将它放在变量声明的前面允许您使用保留关键字作为变量名。

例如:

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>

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


K
Konrad Rudolph

由于您也明确要求使用 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 字符串连接运算符。同样可以使用 +。)


哦,天哪,这听起来很烦人......更高兴我现在正在使用 C#:p
您不能将换行符嵌入到 VB 字符串文字中,即使您可以嵌入到 C# 的逐字字符串文字中。因此它们不一样。
@Svish,等等我错过了什么吗?这根本不是 VB 的缺点。事实上,这是 VB 赢得 C# 的地方之一。最好这样做并明确连接换行符和特殊字符,而不是在 "" 之间抛出所有特殊字符。
@Pacerier 那是胡说八道。一旦你做的不仅仅是琐碎的字符串处理,适当的字符串构建工具是必不可少的,而简洁处理特殊字符的能力是其中最重要的。但是,C# 和 VB 都有 String.Format,它允许这样做。事实上,我现在从不编写 "x" & Environment.NewLine,而是总是使用 String.Format("x{0}", Environment.Newline) 等。不过,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,这是与我们上面所做的比较无关的另一个问题。
E
Ed Guiness

http://msdn.microsoft.com/en-us/library/aa691090.aspx

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

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

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


J
Jon Skeet

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

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

ETC


马克,你是不是错过了你的例子中的@?还是我使用 var 时的默认值?有点迷茫...
好的 - 这真的很奇怪。我想知道编辑是否咀嚼它们?
J
Joey

MSDN 复制:

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


恕我直言,这是典型的误导性 Microsoft 文档!上面所说的最终结果是正确的,但基本事实是 C# 中的字符串被转换为相关的字节序列(或多字节字符代码)。 C# 允许使用两种不同的方式来表示底层字符串,使用 @"..." 或 "..."。调试器总是选择“...”方式,并且无法分辨出首先使用的是哪种方式。 (诸如 \n 或 "" 之类的转义序列仅与编程和显示级别的字符串表示相关,并且永远不会存储在底层字符串中!)
s
senshin

@ 放在字符串前面使您可以使用反斜杠或双引号等特殊字符,而无需使用特殊代码或转义字符。

所以你可以写:

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

代替:

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

M
Mage Xy

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