【发布时间】:2019-01-01 01:39:30
【问题描述】:
这是我的帖子Is this a correct implementation of a concurrent observable collection? 的后续。
在那篇文章中,我有一个实现通用并发可观察列表的自定义类,包括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 字段,只要实际内部集合 (List<T> _list) 被修改,就会使用 lock() 重新构建。
但现在我觉得localSnapshot这个变量根本不需要,代码应该是:
public IEnumerator<T> GetEnumerator()
{
return ((IEnumerable<T>)_snapshot).GetEnumerator();
}
因为localSnapshot 被简单地分配了对_snapshot 引用的同一地址的引用。 GetEnumerator 不关心(也无法分辨)使用了哪个变量(当然,它会为自己创建另一个引用同一数组的变量)。
如果我的上述假设是正确的,我想知道编译器是否会将变量优化掉?然后生成的代码将是相同的。或者,如果不是:理论上复制引用可能是“有害的”,因为副本的更新程度将低于可能的情况(另一个线程可以在复制完成后刷新_snapshot,但在GetEnumerator 之前叫做)?而且,编译器不优化代码的原因是“副作用”吗?因为优化是“无副作用”的?
【问题讨论】:
-
要可靠地回答这个问题,您需要自己测试一下,语言编译器,或者很可能 Jitter 可以很好地优化它。如果您发现自己在问这些问题,检查发布模式下的IL,也可以使用sharplab.io或其他工具检查asm
-
在这种情况下,优化将由编译器完成。相同代码的两个版本将产生相同的 IL 这两个代码 sn-ps 在功能上没有区别
标签: c# multithreading compiler-optimization