C#编译器会优化掉变量吗?

麦克风

这是我的文章的后续文章,这是并发可观察集合的正确实现吗?

在那篇文章中,我有一个自定义类,该类实现了通用的并发可观察列表,包括的实现IEnumerable<T>.GetEnumerator()这是原始代码:

public IEnumerator<T> GetEnumerator()
{
    var localSnapshot = _snapshot; //create local variable to protect enumerator, if class member (_snapshot) should be changed/replaced while iterating
    return ((IEnumerable<T>)localSnapshot).GetEnumerator();
}

_snapshot作为一个私人Array正在使用的重新生成的字段lock()每当实际内集合(List<T> _list)被修改。

但是现在我认为localSnapshot根本不需要变量,代码应该是:

public IEnumerator<T> GetEnumerator()
{
    return ((IEnumerable<T>)_snapshot).GetEnumerator();
}

因为localSnapshot简单地将引用分配给与引用相同的地址_snapshotGetEnumerator不在乎(也无法说出)使用了哪个变量(当然,它会为自己使用而创建另一个引用同一数组的变量)。

如果我的上述假设是正确的,我想知道编译器是否会将变量优化掉?那么结果代码将是相同的。或者,如果不是:从理论上讲,复制引用是否可能“有害”,因为该副本将比其更新的版本少(另一个线程可以_snapshot在创建副本之后但在GetEnumerator调用之前刷新)?并且,这种“副作用”是编译器不优化代码的原因-因为优化是“无副作用的”吗?

凯文·高斯

编译后,这两个版本的代码将产生相同的结果。正如TheGeneral在评论中指出的那样,一种确保确认的好方法是检查sharplab.io

请注意,仅当您在发布模式下编译时,这才是正确的。如果以Debug模式进行编译,则编译器将假定您可能需要中介变量来进行调试,并且不会对其进行优化。

从理论上讲,甚至可以复制引用是“有害的”,因为该副本将比其更新的版本少(另一个线程可以在创建副本之后但在调用GetEnumerator之前刷新_snapshot)

如果您在var localSnapshot = _snapshot;之间执行了一些代码,就会出现这种情况return ((IEnumerable<T>)localSnapshot).GetEnumerator()在那种情况下,优化是不可能的。否则,在两种情况下,您都将读取值并直接使用它。两个版本的代码之间的“新鲜度”没有区别。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章