Pet*_*lek 37 c# variable-declaration
我们的内部审计建议我们使用显式变量类型声明而不是使用关键字var.他们认为使用var"可能会在某些情况下导致意外结果".
var一旦代码编译成MSIL,我不知道显式类型声明和使用之间的任何区别.
审计员是一位受人尊敬的专业人士,所以我不能简单地拒绝这样的建议.
Luk*_*keH 50
这个怎么样...
double GetTheNumber()
{
// get the important number from somewhere
}
Run Code Online (Sandbox Code Playgroud)
其他地方......
var theNumber = GetTheNumber();
DoSomethingImportant(theNumber / 5);
Run Code Online (Sandbox Code Playgroud)
然后,在未来的某个时刻,有人注意到GetTheNumber只返回整数,所以重构它int而不是返回double.
砰! 没有编译器错误,你开始看到意外的结果,因为以前的浮点运算现在已成为整数运算而没有任何人注意到.
话虽如此,这种事情应该是你的单元测试等,但它仍然是一个潜在的问题.
Chr*_*isF 23
我倾向于遵循这个方案:
var myObject = new MyObject(); // OK as the type is clear
var myObject = otherObject.SomeMethod(); // Bad as the return type is not clear
Run Code Online (Sandbox Code Playgroud)
如果返回类型SomeMethod永远改变,那么此代码仍将编译.在最好的情况下,您会进一步得到编译错误,但在最坏的情况下(取决于myObject使用方式)您可能不会.在这种情况下你可能得到的是运行时错误,这可能很难追查.
Dar*_*mas 14
有些情况可能会导致意想不到的结果.我var自己也是粉丝,但这可能会出错:
var myDouble = 2;
var myHalf = 1 / myDouble;
Run Code Online (Sandbox Code Playgroud)
显然这是一个错误而不是"意外结果".但这是一个问题......
bad*_*d99 13
var不是动态类型,它只是语法糖.唯一的例外是Anonymous类型. 来自Microsoft Docs
在许多情况下,var的使用是可选的,只是语法上的便利.但是,当使用匿名类型初始化变量时,如果需要稍后访问对象的属性,则必须将变量声明为var.
编译为IL之后没有区别,除非您已明确将类型定义为与隐含的类型不同(尽管我无法想到您为什么会这样).编译器不允许在任何时候更改用var声明的变量的类型.
从Microsoft文档(再次)
隐式类型的局部变量是强类型的,就像您自己声明了类型一样,但编译器确定了类型
在某些情况下,var会妨碍可读性.更多Microsoft文档声明:
使用var确实至少有可能使您的代码对其他开发人员更难理解.因此,C#文档通常仅在需要时才使用var.
在非泛型世界var中,每当发生隐式转换时(例如在foreach循环内)使用而不是类型时,您可能会得到不同的行为.
在下面的例子中,从隐式转换object到XmlNode发生(非通用IEnumerator接口只返回object).如果只是用var关键字替换循环变量的显式声明,则不再发生此隐式转换:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果是,根据您使用的var还是显式类型,此代码实际上会产生不同的输出.随着var该Foo(object)超载将被执行,否则Foo(XmlNode)过载会.因此,上述计划的产出是:
XmlNode overload object overload
请注意,此行为完全符合C#语言规范.唯一的问题是var推断出一种不同于你期望的类型(object),并且通过查看代码,这种推断并不明显.
我没有添加IL以保持简短.但是如果你想要,你可以看看ildasm,看看编译器实际上为两个foreach循环生成不同的IL指令.
这是一个奇怪的说法,即var永远不应该使用使用,因为它"在某些情况下可能会导致意想不到的结果",因为C#语言中的微妙之处远比使用它复杂得多var.
其中之一是匿名方法的实现细节,这些方法可能导致R#警告"访问修改后的闭包"以及与查看代码时非常不同的行为.不同于几句话var可以解释,这种行为需要三篇很长的博客文章,其中包括反汇编程序的输出,以便完整解释:
这是否意味着您也不应该使用匿名方法(即委托,lambdas)和依赖它们的库(如Linq或ParallelFX),因为在某些奇怪的情况下,行为可能不是您所期望的?
当然不是.
这意味着您需要了解您正在编写的语言,了解其局限性和边缘情况,并测试事情是否按预期工作.排除语言功能的基础是"在某些情况下可能会导致意外结果",这意味着您只能使用很少的语言功能.
如果他们真的想争论折腾,请他们证明你的一些错误可以直接归因于使用,var并且显式类型声明会阻止它们.我怀疑你很快会收到他们的回复.
| 归档时间: |
|
| 查看次数: |
6124 次 |
| 最近记录: |