如果局部(但未使用)变量是对对象的唯一强引用,那么符合标准的 C# 编译器是否可以优化它?
另请参阅这些相关资源:
- .NET 垃圾收集器是否对代码进行预测分析?(在 Stack Overflow 上)
- WP7:GC 何时将局部变量视为垃圾(MSDN 上的博客文章)
换句话说:
一个对象可以被本地引用吗? 变量在之前被回收 变量超出范围(例如 因为变量已被赋值,但是 然后不再使用),或者是这样 保证不符合条件的对象 垃圾回收直到变量 超出范围?
让我解释一下:
void Case_1()
{
var weakRef = new WeakReference(new object());
GC.Collect(); // <-- doesn't have to be an explicit call; just assume that
// garbage collection would occur at this point.
if (weakRef.IsAlive) ...
}
在这个代码示例中,我显然必须计划新的对象
被垃圾收集器回收的可能性;因此是 if
语句。
(请注意,我使用 weakRef
的唯一目的是检查新的 object
是否仍然存在。)
void Case_2()
{
var unusedLocalVar = new object();
var weakRef = new WeakReference(unusedLocalVar);
GC.Collect(); // <-- doesn't have to be an explicit call; just assume that
// garbage collection would occur at this point.
Debug.Assert(weakRef.IsAlive);
}
此代码示例相对于上一个示例的主要变化是新的对象
被局部变量(unusedLocalVar
)强引用。但是,在创建弱引用 (weakRef
) 后,该变量将不再使用。
问题:如果合格的 C# 编译器发现 unusedLocalVar<,是否允许将
Case_2
的前两行优化为 Case_1
的前两行/code> 仅在一个地方使用,即作为 WeakReference
构造函数的参数?即 Case_2
中的断言是否有可能失败?
See also these related resources:
- Does the .NET garbage collector perform predictive analysis of code? (on Stack Overflow)
- WP7: When does GC Consider a Local Variable as Garbage (blog article on MSDN)
In other words:
Can an object referenced by a local
variable be reclaimed before the
variable goes out of scope (eg.
because the variable is assigned, but
then not used again), or is that
object guaranteed to be ineligible for
garbage collection until the variable
goes out of scope?
Let me explain:
void Case_1()
{
var weakRef = new WeakReference(new object());
GC.Collect(); // <-- doesn't have to be an explicit call; just assume that
// garbage collection would occur at this point.
if (weakRef.IsAlive) ...
}
In this code example, I obviously have to plan for the possibility that the new'ed object
is reclaimed by the garbage collector; therefore the if
statement.
(Note that I'm using weakRef
for the sole purpose of checking if the new'ed object
is still around.)
void Case_2()
{
var unusedLocalVar = new object();
var weakRef = new WeakReference(unusedLocalVar);
GC.Collect(); // <-- doesn't have to be an explicit call; just assume that
// garbage collection would occur at this point.
Debug.Assert(weakRef.IsAlive);
}
The main change in this code example from the previous one is that the new'ed object
is strongly referenced by a local variable (unusedLocalVar
). However, this variable is never used again after the weak reference (weakRef
) has been created.
Question: Is a conforming C# compiler allowed to optimize the first two lines of Case_2
into those of Case_1
if it sees that unusedLocalVar
is only used in one place, namely as an argument to the WeakReference
constructor? i.e. is there any possibility that the assertion in Case_2
could ever fail?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
C# 编译器做什么并不重要 - 一旦本地引用在方法体中不再存在,JITter/GC 就可以清理它们。查看 GC.KeepAlive 的文档
另外,这个PowerPoint 演示文稿,特别是从幻灯片 30 开始,有助于解释 JIT/GC 可以做什么。
It doesn't matter what the C# compiler does - the JITter/GC are allowed to clean up local references once they're no longer alive in a method body. Look at the docs for GC.KeepAlive
Also, this powerpoint presentation, especially from slide 30 onwards, helps to explain what the JIT/GC can get up to.
虽然我的问题已得到解答,但我想我应该发布我刚刚在 MSDN 博客文章 "WP7:GC 何时将局部变量视为垃圾" 作者:abhinaba:
这说明了一切。上述文章还指出,.NET 框架(至少在发布模式下)将执行预测分析并释放此类对象,而 .NET Compact Framework 不会(出于性能原因)。
While my question has been answered, I thought I'd post this relevant piece of information I just found on the MSDN blog article "WP7: When does GC Consider a Local Variable as Garbage" by abhinaba:
This says it all. The mentioned article also says that the .NET framework (at least in Release mode) will perform predictive analysis and free such objects, while the .NET Compact Framework won't (for performance reasons).
这两个定义是等效的,因此从一个定义转换到另一个定义并不是“优化”,因为两者都没有更有效。
是的。生产编译器不太可能保留不必要的引用,因此它将被删除,GC 不会将其视为全局根并会收集该对象。
请注意,垃圾收集器看不到您的程序的变量和作用域。当您的代码到达垃圾收集器时,这些高级概念早已被编译掉了。 GC 只看到寄存器、线程堆栈和全局变量。
The two definitions are equivalent so transforming from one to the other is not an "optimization" because neither is more efficient.
Yes. A production compiler is not likely to retain a reference unnecessarily so it will be removed, the GC will not see it as a global root and will collect that object.
Note that garbage collectors do not see your program in terms of variables and scope. Those high-level concepts have long since been compiled away by the time your code gets to the garbage collector. The GC sees only registers, thread stacks and global variables.