C# 收藏如何';长度';在for循环中访问的属性

C# 收藏如何';长度';在for循环中访问的属性,c#,C#,我知道在下面的代码中,数组“Length”属性不会在每次循环迭代时调用,因为Jit编译器足够聪明,可以将其识别为属性(而不是方法),并优化代码,使其仅在内部存储临时变量中的值时调用它: Int32[] myArr = new Int32[100]; for(Int32 index = 0; index < myArr.Length; index++) { // Do something with the current item } Int32[]myArr=newint32[100];

我知道在下面的代码中,数组“Length”属性不会在每次循环迭代时调用,因为Jit编译器足够聪明,可以将其识别为属性(而不是方法),并优化代码,使其仅在内部存储临时变量中的值时调用它:

Int32[] myArr = new Int32[100];
for(Int32 index = 0; index < myArr.Length; index++) {
// Do something with the current item
}
Int32[]myArr=newint32[100];
对于(Int32索引=0;索引
因此,开发人员不需要尝试通过将长度缓存到局部变量来优化它。 我的问题是:对于.Net中的所有集合类型都是这样吗?例如,假设我有一个列表,并在For循环中调用“Count”属性。我不应该优化这个吗

我知道在下面的代码中,数组“Length”属性不会在每次循环迭代中调用,因为Jit编译器足够聪明,可以将其识别为属性(而不是方法)

虽然从类型系统的角度来看,Length是一个属性,但从抖动的角度来看,它是一个专门用于加载数组长度的特殊指令。这就是使抖动能够执行此优化的原因

我还注意到,有一个更大的优化,你没有提到。检查长度很便宜。这里更大的优化是抖动可以省略对数组中索引操作的检查,因为它知道循环变量将始终在数组的边界内。由于这些检查可以抛出异常,通过省略它们,抖动可以更容易地分析方法的控制流,因此可以对方法的其余部分进行更好的优化

对于.Net中的所有集合类型都是这样吗

如果抖动可以证明这样做是正确的,那么它可以对其他收集类型进行优化。不管它是否真的这样做,你都可以用科学来测试;观察抖动产生的代码,看看它是否有这种优化。我的猜测是抖动没有这种优化

例如,假设我有一个列表,并在For循环中调用“Count”属性。我不应该优化这个吗

现在我们来谈谈问题的真正症结所在。绝对不应该优化这个。优化是难以置信的昂贵;你的雇主会为你优化代码的每一分钟支付报酬,所以你应该优化能产生最大用户可观察收益的东西。获取列表的计数需要纳秒。世界上没有一个程序在市场上的成功取决于是否有人从不必要地检查列表计数的循环中删除了几纳秒

花费时间进行性能优化的方法首先是制定一个以客户为中心的目标。这让你知道什么时候你可以不再担心性能,把钱花在更重要的事情上。第二,每天根据这一目标衡量进展情况。第三,如果且仅当您没有达到目标时,使用探查器来确定代码实际性能不足的地方。然后优化这件事,并且只优化那件事


纳米优化不是设计性能的方法。它们只是使代码更难阅读和维护。在分析性能时使用良好的工程规程,而不是收集技巧和窍门。

您知道的是不对的。属性getter不需要在每次调用时返回相同的值,因此抖动不会假设每次调用时返回相同的值。即使需要属性这样做,也不会阻止
myArr
在循环中被重新分配。虽然抖动可能能够优化你的问题,但它这样做的原因并不是你给出的原因。你的假设是不正确的。属性总是被评估的,因为它们在每次迭代中都可能发生变化。但在房地产方面,成本(应该)几乎为0,所以不要进行微观优化。很可能是重复的:是的,为在这样的数组上迭代而生成的IL将为每次迭代发出IL
ldlen
指令。执行了一个快速测试:使用局部变量和不使用局部变量。对于数组中的100000个元素,我得到了下一个结果:不带局部变量:8590毫秒,使用局部变量表示长度:9151毫秒。因此,如果不缓存,它的工作速度会更快。@hvd:Length不是数组的属性。有一个特殊的IL指令来获取数组的长度,抖动知道它将始终返回相同的值。抖动也知道循环中是否有赋值,C ^使它比C++更容易检测混叠。