【问题标题】:var: a Type or a keywordvar:类型或关键字
【发布时间】:2011-04-11 01:17:07
【问题描述】:

MSDNvar 归类为Types

在方法中声明的变量 scope 可以有一个隐式类型 var

在这种情况下,“隐式类型 var”是什么意思?

严格来说,如果我有它来解释给其他程序员。

我能说吗? var 是一个 Type,还是我不得不说; var 是一个关键字,它指示编译器自行确定类型。

注意:这并不是要开始讨论 var,也不是要学习 var 的用法。一劳永逸地我想知道如何描述它,msdn有点混乱,就是这样。

【问题讨论】:

    标签: c# language-features


    【解决方案1】:

    varcontextual keyword - 例如 yieldaddget

    换句话说,您可以将其用作标识符,而无需在其前面加上@,但它在某些地方对编译器仍有特殊含义(即,在局部变量声明中需要类型名称的地方)。

    使用var 声明一个局部变量要求编译器推断基于右侧表达式的变量类型。例如:

    var list = new List<string>();
    var anon = new { Foo = "bar" };
    

    list 的类型是List&lt;string&gt;anon 的类型是匿名类型,同样在 C# 3 中引入。在 C# 3 中引入 var 的部分原因是允许使用匿名类型的强类型变量 - 变量仍然具有适当的编译时类型,即使您无法明确声明该类型。

    在某些情况下var 不起作用,但是,如果编译器没有足够的信息:

    var cantUseNull = null;
    var cantUseLambda = x => x.Length;
    

    还有其他的。在每种情况下,您可以将表达式转换到右侧,以便编译器知道要使用什么 - 但在这种情况下,您最好直接显式声明变量。

    &lt;plug&gt;
    您可以在C# in Depth 中阅读更多相关信息。幸运的是,仍然可以从first edition page 免费获得涵盖此内容的章节(您需要第 8 章)。我不记得我在第二版中对这一章做了多少改动...
    &lt;/plug&gt;

    【讨论】:

    • 你能解释一下我引用的 msdn 文章中的“隐式类型变量”是什么意思吗?在这里翻译有点迷失;)稍微编辑了这个问题,你的速度太快了......
    • @Caspar:表示可以使用var来声明变量的类型,此时变量的编译时类型就是右边表达式的类型.
    • 重要的是不要丢失那里的格式,它是“隐式类型 var”。 Var 是一种隐式类型,因为实际类型由编译器根据分配给它的内容来确定,即var i = 10;,而不是显式类型的变量,即int i = 10; Implicit 真正意味着隐含或推断的类型。这有帮助吗?
    • @Caspar:我已经稍微扩展了我的答案——但是如果你下载 C# 的第 8 章深度第一版,那就更详细了 :)
    【解决方案2】:

    我可以说 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”不引用类型。相反,它是编译器推断本地实际类型的指令。

    【讨论】:

    • 感谢您的回答,我确实看到您所描述的 public class var{} 覆盖了 var 关键字,所以您的解释对我来说真的很有意义,谢谢! PS:这是否意味着我必须降级乔恩? ;)
    • 在代码中 IDENTIFIERTHATMIGHTBEAKEYWORD 就是这样做的,在 var x= 123 中,var 可能是一个关键字
    • 我不知道您可以创建一个类型 var 来覆盖关键字,但我认为有必要保持向后兼容性。出于好奇,有没有办法仍然使用var 作为关键字,即使这样的类型在范围内?
    • @Dan:不。 “我的意思是这是一个标识符”有一种语法,即在关键字前面加上@。但是没有任何语法可以反过来。
    【解决方案3】:

    两者兼而有之。从技术上讲,当使用 var 时,变量是强类型的,但编译器确定类型。所以我想说'var is a type'时你会最接近。

    【讨论】:

      【解决方案4】:

      var 是一个类型,就像 int 是......但它到底是什么类型?

      好吧,编译器会根据该行的其余部分为您解决这个问题(这是隐含的意思)。

      例如

      var b = "ahjhsad";
      

      在编译时,var 将被替换为 string

      var 被用作程序员方便的简写,而不是必须编写

      List<string> myList = new List<string>();
      

      程序员会写

      var myList = new List<string>();
      

      意思是一样的。

      【讨论】:

      • “究竟什么是类型?”一个好问题。 C# 规范实际上并未定义“类型”一词。它假设你知道一个是什么!
      猜你喜欢
      • 2015-09-14
      • 2016-09-07
      • 2020-11-14
      • 2022-12-31
      • 2012-10-08
      • 2016-09-19
      • 2011-10-06
      • 1970-01-01
      • 2011-09-30
      相关资源
      最近更新 更多