C#中标识符的@前缀

允许使用“@”字符作为前缀,以使关键字可用作标识符。 大多数.net开发人员都知道这一点。

但我们可能不知道:如果删除“@”前缀后两个标识符相同,则认为它们是相同的。

所以

static void Main(string[] args) { int x = 123; Console.WriteLine(@x); } 

绝对有效的代码并打印123到控制台。

我很好奇为什么我们在规范中有这样的规则,以及如何在现实世界的情况下使用这个特征(如果它们不是关键字,用“@”作为标识符的前缀是没有意义的,对吧?)。

这完全合乎逻辑。 @不是名称的一部分,但是一个特殊的指标,不作为关键字处理后来的东西,而是作为标识符。

Eric Lippert有一篇非常好的文章: Verbatim Identifier

我偶尔会问为什么任何标识符都可以作为逐字标识符。 为什么不将逐字标识符限制为保留和上下文关键字?

答案很简单。 想象一下,我们回到了C#2.0发布的那一天。 你有一个C#1.0程序,它使用yield作为标识符,这是完全合理的; “产量”是许多商业和科学应用中的常用术语。 现在,C#2.0经过精心设计,因此使用yield作为标识符的C#1.0程序仍然是合法的C#2.0程序; 它只有在返回之前出现时才具有其特殊含义,并且在C#1.0程序中从未发生过。 但是,您仍然决定将程序中的yield的用法标记为逐字标识符,以便将来的代码读者更清楚它是否被用作标识符,而不是迭代器的一部分

让我们考虑一个生成C#代码的程序示例 – 例如,在数据库表中获取列并创建可比较的C# POCO对象,每列有一个属性。

如果其中一个列名与C#关键字匹配怎么办? 如果所有属性名称都以@为前缀,则代码生成器不必记住哪些单词是关键字。
这是一个故障安全的。 额外的@字符根本不会伤害代码!!

其他答案非常清楚行为存在的原因,但我认为值得看一下标识符被视为相等的规则。

引用规范部分2.4.2:

如果在应用以下转换后它们相同,则认为两个标识符相同,顺序如下:

  • 如果使用前缀“@”,则将其删除
  • 每个unicode-escape-sequence都会转换为相应的Unicode字符。
  • 删除任何格式字符

遵循这些规则,@ xx相同。

它提供了确定性:

  • 使用@word是面向未来的。
    如果稍后成为关键字,则无需进行任何更改。
  • 大多数程序员不熟悉每个关键字(C#有大约100个关键字)
  • 最近的关键字是“上下文”,因此有时它们不是关键字。