这是我之前发布的文章"这是一个并发可观察集合的正确实现吗?"的跟进内容。
在那篇文章中,我有一个自定义类,实现了一个通用并发可观察列表,包括
因为
如果我上面的假设是正确的,我想知道编译器是否会优化掉这个变量?那么生成的代码将是相同的。或者,如果不能:复制引用在理论上甚至可能会是“有害”的,因为复制将比它可以更及时地更新(另一个线程可以在复制完成后但在调用
在那篇文章中,我有一个自定义类,实现了一个通用并发可观察列表,包括
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();
}
当实际内部集合(List<T> _list
)被修改时,_snapshot
是一个私有的Array
字段,使用lock()
重建。
但现在我认为根本不需要localSnapshot
变量,代码应该是:
public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)_snapshot).GetEnumerator();
}
因为
localSnapshot
只是分配了一个指向与_snapshot
相同地址的引用。 GetEnumerator
并不关心(也无法知道)使用了哪个变量(当然,它将为自己使用创建另一个变量,该变量引用相同的数组)。如果我上面的假设是正确的,我想知道编译器是否会优化掉这个变量?那么生成的代码将是相同的。或者,如果不能:复制引用在理论上甚至可能会是“有害”的,因为复制将比它可以更及时地更新(另一个线程可以在复制完成后但在调用
GetEnumerator
之前刷新_snapshot
)。而且,这种“副作用”是编译器不优化代码的原因吗——因为优化应该是“无副作用”的?