代码之家  ›  专栏  ›  技术社区  ›  Petr Kozelek

变量声明中“var”类型的使用

  •  37
  • Petr Kozelek  · 技术社区  · 14 年前

    var . 他们认为使用 变量 “在某些情况下可能导致意想不到的结果”。

    变量 一旦代码被编译成MSIL。

    审计员是一位受人尊敬的专业人士,所以我不能简单地拒绝这样的建议。

    18 回复  |  直到 14 年前
        1
  •  50
  •   LukeH    14 年前

    double GetTheNumber()
    {
        // get the important number from somewhere
    }
    

    然后在别的地方。。。

    var theNumber = GetTheNumber();
    DoSomethingImportant(theNumber / 5);
    

    然后,在未来的某个时刻,有人注意到 GetTheNumber 只返回整数,所以重构它以返回 int 而不是 double .

    话虽如此,这种事 被你的单元测试等抓住了,但这仍然是一个潜在的问题。

        2
  •  22
  •   ChrisF    14 年前

    我倾向于遵循这个计划:

    var myObject = new MyObject(); // OK as the type is clear
    
    var myObject = otherObject.SomeMethod(); // Bad as the return type is not clear
    

    如果返回类型 SomeMethod 一旦发生变化,那么这段代码仍然可以编译。在最好的情况下,您会进一步得到编译错误,但在最坏的情况下(取决于如何编译) myObject 你可能不会。在这种情况下,您可能会得到运行时错误,这可能非常难以跟踪。

        3
  •  13
  •   Daren Thomas    14 年前

    有些案例真的会导致意想不到的结果。我是一个 var 扇我自己,但这可能会出错:

    var myDouble = 2;
    var myHalf = 1 / myDouble;
    

    显然,这是一个错误,而不是一个“意外的结果”。但是它 明白了。。。

        4
  •  13
  •   badbod99    14 年前

    var不是动态类型,它只是 syntactic sugar . 唯一的例外是匿名类型。 From the Microsoft Docs

    在许多情况下,var的使用是可选的,只是一种语法上的便利。但是,当使用匿名类型初始化变量时,如果以后需要访问对象的属性,则必须将该变量声明为var。

    编译成IL后没有区别 除非您已经显式定义了与隐含类型不同的类型(尽管我想不出您为什么会这样做) . 编译器不允许您在任何时候更改用var声明的变量的类型。

    Microsoft documentation

    隐式类型的局部变量是强类型的,就像您自己声明了类型一样,但是编译器确定了类型

    在某些情况下,var可能会提高可读性。更多 Microsoft docs

    var的使用至少有可能使其他开发人员更难理解您的代码。因此,C文档通常仅在需要时才使用var。

        5
  •  8
  •   Dirk Vollmar    14 年前

    在非泛型世界中,使用 var 而不是在隐式转换发生时的类型,例如在 foreach 循环。

    在下面的示例中,从 object XmlNode 发生(非通用) IEnumerator 只返回接口 对象 ). 如果您只需将循环变量的显式声明替换为 变量 关键字,此隐式转换不再发生:

    using System;
    using System.Xml;
    
    class Program
    {
        static void Foo(object o)
        {
            Console.WriteLine("object overload");
        }
    
        static void Foo(XmlNode node)
        {
            Console.WriteLine("XmlNode overload");
        }
    
        static void Main(string[] args)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml("<root><child/></root>");
    
            foreach (XmlNode node in doc.DocumentElement.ChildNodes)
            {
                Foo(node);
            }
    
            foreach (var node in doc.DocumentElement.ChildNodes)
            {
                // oops! node is now of type object!
                Foo(node);
            }
        }
    }
    

    结果是,根据您是否使用 或显式类型。与 变量 这个 Foo(object) 将执行重载,否则 Foo(XmlNode) 超载将是危险的。因此,上述程序的输出为:

    XmlNode overload
    object overload
    

    变量 推断出不同的类型( 对象 从代码来看,这个推论并不明显。

    我添加IL并不是为了保持简短。但是如果你想,你可以看看ildasm,看看编译器实际上为两个foreach循环生成了不同的IL指令。

        6
  •  7
  •   Greg Beech    14 年前

    使用 var 变量

    其中之一是匿名方法的实现细节,它可能导致出现警告“访问修改的闭包”和行为,而这些行为与您在查看代码时所期望的非常不同。不像 变量

    这是否意味着您也不应该使用匿名方法(即委托、lambda)和依赖它们的库(如Linq或ParallelFX),仅仅因为在某些奇怪的情况下,行为可能不是您所期望的?

    当然不是。

    这意味着你需要理解你所用的语言,了解它的局限性和边缘情况,并测试它们是否按你所期望的那样工作。以“在某些情况下可能会导致意外结果”为理由排除语言功能意味着您只剩下很少的语言功能可供使用。

    如果他们真的想争论这个问题,请他们证明您的一些bug可以直接归因于 变量 显式类型声明会阻止它们。我怀疑你会很快收到他们的回信。

        7
  •  4
  •   kemiller2002    14 年前

    他们认为使用var“可能导致

    var my_variable = null
    or
    var my_variable;
    

        8
  •  4
  •   Daren Thomas    14 年前

    当提出指导方针时,作为一个审计人员必须做的是,最好是站在审计人员一边犯错 .

    如果你只是说“不要用 var

    我个人喜欢 变量 变量 ,但用于初始化变量的(命名)方法存在问题。。。

        9
  •  1
  •   Pieter Germishuys    14 年前

    在大多数情况下,我将var与linq一起使用,因为我可能希望返回一个匿名类型。

        10
  •  1
  •   user304117 user304117    14 年前

    ArrayList<Entity> en = new ArrayList<Enity>()
    

    使可读性复杂化

    var en = new ArrayList<Entity>()
    

        11
  •  1
  •   tia    14 年前

    我用 var Person , Person_Class 等)。

    我不使用 对于基元类型、枚举和字符串。我也不把它用于值类型,因为值类型将被赋值复制,所以变量的类型应该显式声明。

    像我们每天做的那样添加更多的代码行 “在某些情况下导致意外结果” 我们创建的那些bug已经证明了这个论点的有效性,因此我建议永远冻结代码库以防止这种情况发生。

        12
  •  0
  •   Spooks    14 年前

    如果您知道类型将是什么,那么使用var就是惰性代码。它只是更容易和更清晰的阅读。当看到大量的代码时,更简单、更干净总是更好的

        13
  •  0
  •   thecoop    14 年前

    对于使用 var 变量 对于长嵌套泛型类型, foreach 循环和匿名类型,因为我喜欢显式指定所有内容。其他人可能有不同的偏好。

        14
  •  0
  •   Frederik Gheysels    14 年前

    只能在某些情况下使用var;在使用var时,必须在声明时初始化变量。 不能将其后属于另一类型的变量赋给该变量。

        15
  •  0
  •   MrDosu    14 年前

    我看到的使用显式变量声明的“唯一”好处是,通过选择好的类型名,您可以更清楚地说明代码的意图(这比其他任何东西都重要)。var关键字的好处就是Pieter所说的。

        16
  •  0
  •   Alex    14 年前

        17
  •  0
  •   John Egbert    14 年前

    var将编译为可以指定的静态类型。它只是消除了在代码中使用该类型显式的需要。它不是动态类型,在运行时不会/不能更改。我发现在foreach循环中使用它非常有用。

    foreach(var item in items)
    {
    item.name = ______;
    }
    

    在处理枚举时,有时某个特定类型的查找时间是未知的。使用var而不是静态类型将得到相同的结果。

        18
  •  0
  •   awe    12 年前

    float distX = innerDiagramRect.Size.Width / (numObjInWidth + 1);
    

    在这里,计算中的所有类型都是 int ,你会得到一个关于分数可能丢失的警告,因为你在一个 float 变量。

    使用var:

    var distX = innerDiagramRect.Size.Width / (numObjInWidth + 1);
    

    distX 内景 . 如果您打算使用浮点值,这是一个隐藏的逻辑错误,在执行时很难发现,除非它触发 divide by zero 如果此初始计算的结果为<1,则在以后的计算中出现异常。