为什么编译器不优化这段代码

Why isn't compiler optimizing away this code

我有一个使用第三方工具迭代点集合的代码。

for (int i = 0; i < pcoll.PointCount; i++) { /* ... */ }

通过 dotTrace 进行分析时,我注意到 PointCount-proerty 每次迭代都会被访问(见上图)

.

我预计此 属性 的值会被编译器优化掉,但显然这并没有发生。也许这实际上是基于 COM 的第 3 方库中的问题,或者在收集信息时也是 dotTrace self 中的问题。

我不确定这个话题是否更适合 Gis.StackExchange。然而,也许有人知道在什么情况下不会进行优化或如何进行优化。

简单地说,编译器如何知道 pcoll.PointCount 是否会在调用之间发生变化?它不能安全地假设该值将保持不变,因此它不能通过缓存第一次调用 pcoll.PointCount 的值来优化此代码。

它可能在此期间发生了变化。

确实,每次迭代都测试 i < pcoll.PointCount 而不是仅使用 foreach(var point in pcoll) 的原因之一正是因为 you 认为集合可能会在同时,枚举器不保证应对他们枚举的集合的变化。

例如,这不同于通过局部变量访问的数组,因为通过局部变量访问的数组的 Length 可以更改的唯一方法是在本地进行更改。

尽管如此,还是值得记住编译器经常会跳过一些明显的优化,因为众所周知抖动也会进行相同的优化。

字段 的预期优化是正确的。但是 属性 有 setter/getter(访问 属性 实际上是将它们作为方法调用),因此编译器将很难尝试优化它。

要修复,将其设为字段或读取一次

var max = pcoll.PointCount;
for (int i = 0; i < max; i++) { /* ... */ }