var
关键字的示例,得到的答案是尽管只有匿名类型需要,但它仍然被用来使编写代码更加“快速” / 简单,并且“只是因为这样做。”
在阅读此链接(“C#3.0-Var不是Objec”)后,我发现 var
在 IL 中被编译成正确的类型(您将在文章中部看到它)。我的问题是,如果到处都使用
var
关键字,会增加多少 IL 代码量,如果使用会对代码的性能产生可衡量的影响?var
关键字的示例,得到的答案是尽管只有匿名类型需要,但它仍然被用来使编写代码更加“快速” / 简单,并且“只是因为这样做。”
在阅读此链接(“C#3.0-Var不是Objec”)后,我发现 var
在 IL 中被编译成正确的类型(您将在文章中部看到它)。var
关键字,会增加多少 IL 代码量,如果使用会对代码的性能产生可衡量的影响?对于 var
关键字,没有额外的中间语言(IL)代码:对于非匿名类型,生成的 IL 应该是相同的。如果编译器无法创建该 IL,因为它无法确定您打算使用的类型,您将会得到一个编译器错误。
唯一的诀窍是 var
将推断出一个精确的类型,而您可能会手动设置一个接口或父类型。
var i = 42;
(推断类型为int)并不等同于long i = 42;
。因此,在某些情况下,您可能会对类型推断做出错误的假设。如果值不合适,这可能导致难以捉摸的/边缘情况的运行时错误。因此,当值没有明确的类型时,清晰表达类型仍然是一个好主意。例如,var x = new List<List<Dictionary<int, string>()>()>
是可以接受的,但var x = 42
有点含糊不清,应该写成int x = 42
。但每个人都有自己的想法... - Nelson Rothermelvar x = 42;
并不含糊。整型字面量属于类型int
。如果你想要一个长整型字面量,你应该写成var x = 42L;
。 - Brian RasmussenFoo
返回一个List
而不是IList
,那么这三行代码都可以编译,但第三行会像第一行一样而不是像第二行。 - Servy正如Joel所说,编译器在编译时确定了变量应该是哪种类型,实际上这只是编译器为了节省击键而执行的技巧,所以例如:
var s = "hi";
被替换成
string s = "hi";
在产生任何 IL 之前编译器会对其进行处理。生成的 IL 与您键入 string 时完全相同。
既然还没有人提到反射器(reflector)...
如果你编译以下的C#代码:
static void Main(string[] args)
{
var x = "hello";
string y = "hello again!";
Console.WriteLine(x);
Console.WriteLine(y);
}
然后在它上面使用反射器,你会得到:
// Methods
private static void Main(string[] args)
{
string x = "hello";
string y = "hello again!";
Console.WriteLine(x);
Console.WriteLine(y);
}
因此,答案显然是没有运行时性能损失!
对于以下方法:
private static void StringVsVarILOutput()
{
var string1 = new String(new char[9]);
string string2 = new String(new char[9]);
}
IL输出如下:
{
.method private hidebysig static void StringVsVarILOutput() cil managed
// Code size 28 (0x1c)
.maxstack 2
.locals init ([0] string string1,
[1] string string2)
IL_0000: nop
IL_0001: ldc.i4.s 9
IL_0003: newarr [mscorlib]System.Char
IL_0008: newobj instance void [mscorlib]System.String::.ctor(char[])
IL_000d: stloc.0
IL_000e: ldc.i4.s 9
IL_0010: newarr [mscorlib]System.Char
IL_0015: newobj instance void [mscorlib]System.String::.ctor(char[])
IL_001a: stloc.1
IL_001b: ret
} // end of method Program::StringVsVarILOutput
因此,明确地说,这是一种懒惰的编码风格。如果有选择的话,我更喜欢使用本地类型;我愿意多写一点"噪音"以确保在编写和调试代码时我能够准确地阅读和理解它。*耸肩*
var
是否会对性能产生影响的问题;你只是陈述了你对人们是否应该使用它的观点。 - HerohtarC#编译器在编译时推断var
变量的真实类型。生成的IL代码没有区别。
我认为你没有正确理解你所读的内容。如果它被编译为正确的类型,那么就不存在区别了。当我这样做:
var i = 42;
int i = 42;
使用var不会增加运行时性能成本。然而,我认为编译器需要推断类型,因此可能会有编译性能成本,但这很可能是可以忽略不计的。
var x = new ClassA();
ClassA x = new ClassA();
然而,如果你是动态构建类型(如LINQ ...),那么var
就是你唯一的选择,没有其他机制可以用来比较以确定惩罚。
我常在网站文章或指南中使用var这个词。
在线文章的文本编辑器宽度较小。
如果我写下这段内容:
SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();
您会发现,上面呈现的预代码文本过长,超出了框架范围,被隐藏起来。读者需要向右滚动才能看到完整的语法。
这就是为什么我在网页文章中总是使用关键词var的原因。
var coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();
整个渲染的预先代码刚好适合屏幕。
实际上,在声明对象时,我很少使用var,我依赖于智能感知来更快地声明对象。
例如:
SomeCoolNamespace.SomeCoolObject coolObject = new SomeCoolNamespace.SomeCoolObject();
但是,当我需要从一个方法中返回对象时,我使用 var 来更快地编写代码。
例如:
var coolObject = GetCoolObject(param1, param2);
var
声明的变量在 Visual Studio 2019 中绝对可以使用“查找所有引用”功能,因此如果曾经出现过问题,那么现在已经被修复了。但是我可以确认它可以在 Visual Studio 2012 上使用,所以我不确定为什么你声称它不能工作。 - HerohtarX
上使用“查找所有引用”时,var
不会被视为对X
的引用。有趣的是,如果你在该语句中使用“查找所有引用”来查找var
,它 将 显示对X
的引用(尽管它仍然不会列出var
语句)。此外,当光标位于var
上时,它将突出显示同一文档中所有X
的实例(反之亦然)。 - Herohtar