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

标签 c# multithreading compiler-optimization

这是我的帖子 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作为私有(private) Array使用 lock() 重建的字段每当实际的内部集合 ( List<T> _list) 被修改时。

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

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

因为 localSnapshot只是简单地分配了对与 _snapshot 相同地址的引用引用。 GetEnumerator不关心(也不能告诉)使用了哪个变量(并且会为自己使用,当然会创建另一个引用同一数组的变量)。

如果我上面的假设是正确的,我想知道,编译器是否会优化这个变量?那么生成的代码将是相同的。或者,如果不是:理论上复制引用甚至可能是“有害的”,因为副本将比它可能更新的要少(另一个线程可以在复制完成后但在 _snapshot 之前刷新 GetEnumerator叫做)?而且,这种“副作用”是否是编译器不优化代码的原因 - 因为优化是“无副作用”的?

最佳答案

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

请注意,只有在 Release 模式下编译时才会出现这种情况。如果您在 Debug 模式下编译,那么编译器会假设您可能需要中间变量来进行调试,并且不会对其进行优化。

could copying the reference theoretically even be "harmful", because the copy will be less up-to-date than it could be (another thread could refresh _snapshot after the copy was made, but before GetEnumerator is called)

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

关于c# - C# 编译器会优化变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53992541/

相关文章:

ios - DispatchQueue.concurrentPerform 内存损坏

java - 如何配置 spring 来执行重叠的 fixedRate 任务?

c++ - 带 -O2 和不带 -O2 的移位运算符的不同行为

c - 在 C 程序中轮询其他线程写入的变量是否安全?

java - Java中方法、对象、类的同步

c - 在 Code Composer Studio 编译器中禁用 64 位除法

c# - 在 try-catch 中包装 specflow 场景

c# - 是否可以根据 ASP.NET/IIS 中的用户代理进行条件 URL 重写?

c# - Windows Mobile 平台上的 PInvoke

c# - 在 C# 中验证电子邮件地址是否存在