为什么我可以创建一个名为“ var”的类?


103

varC#中不是关键字吗?但是为什么我可以这样做:

public class var { }

public class main
{
    public static void main(string[] args)
    {
        var testVar = new var();
    }
}

var是在代码中使用的是var这是在之前声明的类main类。而且编译器甚至没有抱怨。

当我这样做时:

public class int { }

或这个:

public class true { }

编译器说int或是true关键字,不能那样使用。为什么不一样var呢?


6
你为什么要 如此令人困惑且难以阅读。
duffymo'5


31
很好的问题!
理查德

50
您也可以var var = "var";使用一种方法。毕竟是星期五。
Henk Holterman

11
我猜他们把它这种方式是向后兼容的代码创建之前 “变种”意味着什么特别之处。
vidstige,2012年

Answers:


101

var根据此列表不是关键字。

它是一个上下文关键字,因此编译器可以根据上下文确定哪个是您的类,哪个是上下文关键字,并且不会引起混淆。

上下文关键字是:

用来在代码中提供特定的含义,但这不是C#中的保留字。

因此,由于它不是保留的,您可以使用它。

正如以上评论所指出的那样,在Eric Lipperts博客上讨论了差异以及在每个c#版本上添加的各种关键字和上下文关键字的列表。

有趣的是,由于关键字集是在C#1.0中确定的,因此没有添加关键字,以保持向后兼容性。


1
但是,这里将其归类为“ C#关键字”下的msdn.microsoft.com/en-us/library/bb383973.aspx ...令人困惑!
理查德

4
但这是一个Contextual Keyword“上下文关键字用于在代码中提供特定的含义,但在C#中不是保留字。某些上下文关键字(例如,partial和where在两个或多个上下文中具有特殊含义)。”
蒂姆·施密特

5
@TimSchmelter然后,“ var”是一个“关键字”。只是不是“保留字”,对吗?
luiscubal 2012年

2
我猜这是要保持与旧代码的兼容性-如果某人有一个名为的类,var则升级C#时不会破坏所有内容。
卡勒姆·罗杰斯

1
@CallumRogers:这正是 C#团队这样做的原因。与其他后来引入的“关键字”(例如from,join等)相同(顺便说一下,都是上下文相关的)。
亚伯2012年

18

编译器足够聪明,可以知道您var用作类名的上下文永远不会是关键字的上下文,因此允许使用它(这就是为什么将其定义为上下文关键字)的原因。


我认为这个答案至少在某种程度上具有误导性。编译器不能完全“智能”地确定是否var在诸如之类的代码中用作关键字var testVar = new var();。是的,根据是否定义了自定义类型var来定义上下文,但这恰好是因为在这种情况下,编译器不够聪明,无法知道是var testVar引用该类var还是var默认为其指定的关键字在这种情况下。如果var关键字的名称不同,则可以在相同的“上下文”中使用它。
OR Mapper 2014年

与其他上下文关键字相反,例如add-在这里,编译器确实确实在每次出现时都知道该关键字是否有意义(事件声明;标识符在那里毫无意义),或者代码是否引用了标识符(类型或声明中的名称,在方法主体中使用标识符;在那里,关键字没有任何意义)。
OR Mapper 2014年

12

另一种看待这种情况的方式:“ var”作为关键字不在C#的第一个版本中(与“ int”和“ true”不同),因此您可能已经编写了一些代码,这些代码具有一个名为“ var”的类。这是完全合法的。然后,当在语言中添加“ var”时,设计人员非常友好,只在某些情况下将其作为关键字,因此您现有的var类仍然可以使用。

这是语言设计的真正挑战之一-如何在不破坏现有代码的情况下添加新功能,又不使新功能难以使用。


8

在版本3之前的C#版本中,尚不支持隐式类型的局部变量,因此var它没有特殊含义,并且可以定义名为的变量和类var。您的示例程序是合法的,因为varin的两次出现都main引用了class var

C#3和更高版本向下兼容,因此在版本3之前用C#编写的代码仍可以使用新的编译器进行编译。

inttrue是自C#1起的关键字。


3

可以根据上下文保留关键字。解析源代码时,该上下文将作为解析树的一部分建立。关键字的评估在该上下文中进行。因此,在这种情况下,var不在保留上下文中,并且与在赋值语句中使用它的含义不同。我相信这种灵活性的一个原因是var是在C#3中引入的,因此在所有程序中保留var可能会破坏向后兼容性,而在较早的版本中则不会将其用作变量类型声明,因此没有破损。

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.