我可以说 var 是一个类型,还是我必须说 var 是一个指示编译器确定类型的关键字?
这取决于你如何看待它。说真的!
C# 编译器对程序进行三种分析,每种后续分析都会消耗前一种分析的结果。我们做的第一种分析是词法分析;我们将文本转化为一系列标记。假设你有
class C { static void Main(){ var x = 123; } }
我们首先确定这些标记是 CLASS IDENTIFIER(C) LEFTBRACE STATIC VOID IDENTIFIER(Main) LEFTPAREN RIGHTPAREN LEFTBRACE IDENTIFIERTHATMIGHTBEAKEYWORD(var) IDENTIFIER(x) EQUALS INTEGER(123) SEMICOLON RIGHTBRACE RIGHTBRACE。
在这个分析阶段,“var”是一个标识符,上面有一个注释,说明它可能是关键字 var,而不是标识符 var。
我们要做的下一个分析是语法分析,其中标记被组织成组,形成“分析树”。在这种情况下,令牌将被组织到这棵树中(缩进表示树中的嵌套级别)
declaration of class: CLASS
class name: IDENTIFIER(C)
class body begins: LEFTBRACE
declaration of method:
method modifier: STATIC
return type: VOID
method name: IDENTIFIER(Main)
formal parameter declarations:
formal parameter declarations begin: LEFTPAREN
formal parameter declarations end: RIGHTPAREN
method body:
method body begins: LEFTBRACE
local declaration statement:
type: IDENTIFIERTHATMIGHTBEAKEYWORD(var)
local name: IDENTIFIER(x)
initializer:
assignment operator: EQUALS
integer literal expression: INTEGER(123)
statement ends: SEMICOLON
method body ends: RIGHTBRACE
class body ends: RIGHTBRACE
此时,var 在语法上已被归类为类型。如果这是一个语法合法的程序,它就在我们期望类型声明的地方。
但此时我们不知道“var”是指一种类型还是被用作关键字。这需要语义分析。
当我们对解析树进行语义分析时,我们会说“好的,有一个类 C,它有一个 Main 方法,它声明了一个局部变量 x。那个局部变量的类型是什么?”
此时有两种可能。第一种可能性是全局命名空间中有一个名为“var”的类、结构、枚举、接口或委托类型。 (这个程序片段中没有“using”指令,因此我们不必检查任何其他命名空间,并且类型不是部分的,因此我们不必检查任何其他类型声明)。我们搜索所有引用程序集的全局命名空间,寻找一种名为“var”的类型。我们还对所有其他文件中的类型声明进行语义分析,再次寻找名为 var 的类型。
如果我们找到一个,那么“var”指的是那个类型。
如果我们没有找到,那么我们假设“var”被用作引入隐式类型本地的上下文关键字。
所以,回答你的问题:
在词法上,代码片段“var”是一个标识符标记,上面有一个注释,上面写着“顺便说一句,这实际上可能是一个关键字”。
在语法上,标记“var”是一种类型当它出现在语法中预期类型的位置时。
语义上,类型语法“var”是一个类型当作用域中有一个类型叫做var;如果没有这样的类型并且“var”被用作本地声明的类型,那么类型语法“var”不引用类型。相反,它是编译器推断本地实际类型的指令。