10

我知道 '@' 关键字在 C# 中用于不同目的,如此所述,但我的问题不同。

假设我正在使用@ConfigurationManager.AppSetting["DbConnectionString"]. ConfigurationManager.AppSetting["DbConnectionString"]它仍然以相同的方式工作。

所以我的问题是:

  1. 为什么在不影响其值的情况下编译器允许此处的'@'符号?
  2. '@' 符号可以在上述任何情况下更改值吗?

为了更清楚,我想再添加一个示例:

假设,我有一个类'ConfigurationLoader',它有一个静态函数'GetConfigurations'返回一个字符串列表。

然后,我可以将其称为List<string> ConnectionStrs=ConfigurationLoader.GetConfigurations();.

如果我做到了,List<string> ConnectionStrs=@ConfigurationLoader.GetConfigurations();那么它仍然会给出相同的结果。在这样的情景中,我问了以上两个问题。

4

4 回答 4

24

更新:这个问题是我 2013 年 9 月博客的主题。谢谢你的好问题!


'@' 符号可以在上述任何情况下更改值吗?

不。

我们正在谈论的功能是什么?

在 C# 中,如果您在任何标识符前面加上,@那么该标识符是允许的,但不需要是关键字。此功能允许开发人员使用保留关键字作为标识符:

static void M(bool @unsafe) { ... }

它允许您强调可能与上下文关键字混淆的标识符实际上是标识符:

@yield = 123.45;

如果没有,这将是合法的,@但它清楚地表明,开发人员并不是故意yield return 123.45;的。

那么为什么允许在不是关键字的标识符上使用它呢?

让我们进入 Wayback 机器,回到 C# 2.0 的世界。假设该功能是您建议的方式:@只能使用保留关键字和上下文关键字。你用 C# 2.0 编写这个程序:

class P
{
  static void Main()
  {
    int @yield = 123;
  }
}

尽管没有使用 C# 2.0 的功能,但这是一个合法的C# 2.0程序但不是合法的 C# 1.0 程序,这似乎有点奇怪吗?

该功能的设计允许您在使用不同C# 版本的两个团队之间共享代码。它允许您让团队中的一个人试用 C# 2.0,看看它是否有效,而其他人仍在使用 C# 1.0。您提出的功能使这两种情况都变得噩梦般,并为采用该语言的新版本引入了障碍。升级已经足够昂贵了;语言设计团队不想让它变得更加昂贵。

其设计的功能还支持“面向未来”。假设您正在编写一个生成其他程序的程序。您不妨让生成的程序在其所有标识符前加上前缀,@因为您不知道在未来的 C# 版本中哪些词会成为关键字。

我在哪里可以阅读有关 C# 关键字规则的更多信息?

http://ericlippert.com/2009/05/11/reserved-and-contextual-keywords/

于 2013-06-04T15:54:42.160 回答
6

正如您可能从大量评论中看出的那样,您的问题并没有一个好的、令人满意的答案。不过,我会试一试:

1.为什么这里编译器允许'@'符号不影响其值?

因为这就是语言规范所说的。标记前的 @ 符号并不意味着“下一个标记是关键字,但将其视为标识符”。这不是规范的编写方式,因此语言编译器也不是这样工作的。相反,它的意思是“无论下一个标记是什么,都将其视为标识符,即使它恰好是关键字”。

这与说,例如,“假装蓝色是一种颜色”是一样的。这很容易做到,因为蓝色一种颜色。类似地,说“假装myCollection不是 C# 关键字”很容易——它不是C# 关键字,所以没什么可做的。

我怀疑你真正想问的是:

1b。为什么设计 C# 的人会这样定义@符号的行为?

这个问题,恐怕只有帮助定义 C# 的人才可以回答。我们可以猜到,答案几乎肯定会是几个人已经评论过的那个:因为这种方式更容易(解释、记录、实施、测试等)并且没有缺点。好吧,除了一些开发人员的一些轻微的困惑。:)

在规范中添加要求编译器在“滥用”@符号时执行某些操作意味着大量工作。你必须定义它的作用(它是一个警告吗?错误?),你必须在规范中添加正确、准确、校对、明确的语言,你必须将代码添加到编译器中以产生新的行为,你必须记录新行为,您必须编写测试脚本来练习新行为等。所有这些都是为了一个具有零附加收益的“功能”。

它确实使@的使用变得多余,但是由于各种原因,C# 允许您做很多多余的事情。您可以添加冗余(),可以添加冗余委托构造函数,可以添加冗余可访问性关键字。而且,如您所见,@如果您愿意,可以在各处添加冗余 's。

2. '@' 符号可以在上述任何情况下更改值吗?

这个,我们可以回答:不。如果你把@一个已经是标识符的标记放在前面,它将被视为一个标识符——编译器无论如何都要引用的完全相同的标识符。您不会看到任何行为变化,只是额外输入。

于 2013-06-04T15:07:24.497 回答
0

您引用的问题回答了您的问题。在这种情况下,@告诉编译器下一个符号是标识符,而不是关键字。你不需要它ConfigurationManager,但它仍然可以使用。以下是需要它的示例:

class @class
{
    public @class()
    {
    }
}

class Program
{
    static void Main(string[] args)
    {
        @class c = new @class();
    }
}
于 2013-06-04T13:59:39.740 回答
0

您可以使用该@符号将保留关键字用作简单的变量名称,例如:

int @for = 10;

Console.WriteLine(@for); // 10

同样,您可以使用一个名为@hello而不是 的变量hello,即使hello它不是需要@前缀才能将其用作变量名的保留关键字。

编辑以说明在保留关键字上未使用时允许使用它的真正原因。

两个可能的原因:

  1. @应该只允许在保留关键字(和转义字符串)上使用,但有人忘记了 an而if其他人不在乎。
  2. 应该允许在保留关键字上使用@,并且首先没有人关心它是否也会以其他方式使用。
于 2013-06-04T13:59:49.233 回答