# C#编译器会在循环内优化此操作吗?

Will C# compiler optimize this operation inside a loop?
2020-11-21
•  译文(汉语)
•  原文(英语)

`verticesInnerSides.Length / 2`每次以完整的形式在下面的代码之间编写代码的最佳方法是:

``````for (int i = 0; i < verticesRoof.Length; i++) {
verticesInnerSides[i * NB_VERTICES + verticesInnerSides.Length / 2] = startInside;
verticesInnerSides[i * NB_VERTICES + verticesInnerSides.Length / 2 + 1] = startInside + Vector3.up * HEIGHT_ROOF;
verticesInnerSides[i * NB_VERTICES + verticesInnerSides.Length / 2 + 2] = endInside;
verticesInnerSides[i * NB_VERTICES + verticesInnerSides.Length / 2 + 3] = endInside + Vector3.up * HEIGHT_ROOF;
}
``````

``````myCalculatedVar = verticesInnerSides.Length / 2;
for (int i = 0; i < verticesRoof.Length; i++) {
verticesInnerSides[i * NB_VERTICES + myCalculatedVar] = startInside;
verticesInnerSides[i * NB_VERTICES + myCalculatedVar + 1] = startInside + Vector3.up * HEIGHT_ROOF;
verticesInnerSides[i * NB_VERTICES + myCalculatedVar + 2] = endInside;
verticesInnerSides[i * NB_VERTICES + myCalculatedVar + 3] = endInside + Vector3.up * HEIGHT_ROOF;
}
``````

C#编译器会在第一种情况下优化此操作吗?

.N,大多数优化都应用于CLR层,而不是C#中的IL编译(例如,方法内联).

``````myCalculatedVar = verticesInnerSides.Length / 2;
for (int i = 0; i < verticesRoof.Length; i++) {
int ind = i * NB_VERTICES + myCalculatedVar;
verticesInnerSides[ind] = startInside;
verticesInnerSides[ind + 1] = startInside + Vector3.up * HEIGHT_ROOF;
verticesInnerSides[ind + 2] = endInside;
verticesInnerSides[ind + 3] = endInside + Vector3.up * HEIGHT_ROOF;
}
``````

1. 您为什么要像第一个代码示例那样来做呢?第二个(无需查看编译器)似乎更有效.

2. 根据《代码完成》和许多其他建议:如果不需要,请不要进行优化.

3. 如果需要,只需进行基准测试即可.(关于基准测试时需要注意的内容,有很多主题,博客和答案,但是我相信您将能够找到它们:)

What is the best approach between the code below where `verticesInnerSides.Length / 2` is written in it's complete form each time :

``````for (int i = 0; i < verticesRoof.Length; i++) {
verticesInnerSides[i * NB_VERTICES + verticesInnerSides.Length / 2] = startInside;
verticesInnerSides[i * NB_VERTICES + verticesInnerSides.Length / 2 + 1] = startInside + Vector3.up * HEIGHT_ROOF;
verticesInnerSides[i * NB_VERTICES + verticesInnerSides.Length / 2 + 2] = endInside;
verticesInnerSides[i * NB_VERTICES + verticesInnerSides.Length / 2 + 3] = endInside + Vector3.up * HEIGHT_ROOF;
}
``````

Or the following where it's written outside the loop once :

``````myCalculatedVar = verticesInnerSides.Length / 2;
for (int i = 0; i < verticesRoof.Length; i++) {
verticesInnerSides[i * NB_VERTICES + myCalculatedVar] = startInside;
verticesInnerSides[i * NB_VERTICES + myCalculatedVar + 1] = startInside + Vector3.up * HEIGHT_ROOF;
verticesInnerSides[i * NB_VERTICES + myCalculatedVar + 2] = endInside;
verticesInnerSides[i * NB_VERTICES + myCalculatedVar + 3] = endInside + Vector3.up * HEIGHT_ROOF;
}
``````

Will C# compiler optimize this operation in the first case ?

Talk1:
Why hope the compiler optimizes it for you instead off writing it properly in the first place?
Talk2:
open ILDSM and check for yourself <br/> msdn.microsoft.com/en-us/library/aa309387(v=vs.71).aspx
Talk3:
It appears you are using the parallel array anti pattern. Please consider using objects and OOP.
Talk4:
.N, most optimizations applied at CLR layer, not at C# to IL compilation (method inlining for example).
Solutions1

In my opinion the best way to reach readability and performance is:

``````myCalculatedVar = verticesInnerSides.Length / 2;
for (int i = 0; i < verticesRoof.Length; i++) {
int ind = i * NB_VERTICES + myCalculatedVar;
verticesInnerSides[ind] = startInside;
verticesInnerSides[ind + 1] = startInside + Vector3.up * HEIGHT_ROOF;
verticesInnerSides[ind + 2] = endInside;
verticesInnerSides[ind + 3] = endInside + Vector3.up * HEIGHT_ROOF;
}
``````

But you can waste your time and write some benchmarks test for testing this piece. I am sure that if a bottleneck will exist it will be in another place in the code.

Solutions2
1. Why would you do it like the first code example to begin with ? The second one (without looking at the compiler) seems more efficient.

2. As per Code Complete, and many other suggestions: Don't optimize if you don't need to.

3. If you need to, simply benchmark. (There's plenty of threads, blogs and answers about what to look out for when benchmarking, but I'm sure you'll be able to find them :)

As an extra bonus, here's another answer with all the links you'll need :)

Talk1:
I don't agree with the conventional wisdom that pre-mature optimization "is the root of all evil". Most optimizations come with no cost (like this). They are obvious and also can increase readability, maintainability and safeness. You only have one variable to check or change instead of multiple places in the code. If you don't optimize now, you'll probably never optimize it. It's much more difficult to understand if you can change something without causing problems if you look at the code later.
Talk2:
I absolutely agree about readability. Code should be written to be read. If when you're done, you have a performance issue, find out where, and then optimize that bit. Otherwise, you might be wasting time and making your code harder to read, and at the same time, maybe even slower.