我正在编写一些调试代码,我想知道我在做什么可能会影响性能。
让我们来看看代码:
foreach (var item in aCollection)
Debug.WriteLine(item.Name);
我知道Debug类使用Conditional属性来避免在发布模式下编译(或者每当DEBUG未定义时),但是当在发布模式下编译时,这会最终成为徒劳/空迭代,还是会被编译器?
答案 0 :(得分:7)
您没有在此处利用任何编译器符号。将它包装在这些内容中:
#if DEBUG
// your code here
#endif
这种方法的优点:
[Conditional]
方法属性大大降低了可读性。在调用方面,在编译代码中不会发生调用并不明显。团队应该避免采用这种做法,而采用更明确的条件编译方法。即便评论也是不可取的,因为在大型团队中总会有某人忘记评论这样的内容。相反,上面的示例很容易阅读(当VS2010不是当前构建配置文件的一部分时,VS2010 +甚至会对文本进行阴影处理。)答案 1 :(得分:4)
那个foreach不会被抹去。
编译后的代码如下:
foreach (var item in aCollection)
{
;
}
无论如何都会列举该集合。
答案 2 :(得分:3)
C#编译器不会优化枚举,因为枚举集合的行为可能会产生副作用:
foreach
循环重写为索引循环)。GetEnumerator()
和MoveNext()
的调用意味着副作用。在这两种情况下,潜在的null
取消引用都是副作用。
当调用[Conditional]
方法时,只会从编译的代码中省略方法调用及其形式参数。请注意,即使带有副作用的参数也会被省略。但是,不会忽略周围的代码。
我自己的测试表明,即使对于一个简单的数组,即使添加显式null
检查也不会诱使C#编译器优化掉枚举。
JIT编译器是否优化了枚举代码是另一个问题。它可能,如果它可以证明该集合总是非null
和,则没有其他有意义的副作用。 JIT 可能足够复杂,可以为数组做到这一点;不过,我不会赌它。如果增加的开销涉及到您,请将枚举代码放在#if
区域中,如@pid所示。