Mik*_* B. 4 c# memory wpf optimization destructor
在我的WPF应用程序中,我通过以下方式调用新窗口:
_newWin = new WinWorkers_AddWorker();
_newWin.WindowState = this.WindowState;
_newWin.Show();
Run Code Online (Sandbox Code Playgroud)
哪里_newWin是private Window object.
我的问题是我应该_newWin在调用后分配一个空值_newWin.Show()吗?
这会减少内存消耗,因为垃圾收集器/析构函数会更早地清理空值对象吗?
谢谢.
将值设置为null通常无关紧要.它很少有用.它偶尔会有害.
让我们首先考虑最简单的情况:
private void DoStuff()
{
var newWin = new WinWorkers_AddWorker();
newWin.WindowState = this.WindowState;
newWin.Show();
int irrelevant = 42;
this.whoCares = irrelevant * 7;
int notRelevantEither = irrelevant + 1;
this.stillDontCare = notRelevantEither * irrelevant;
}
Run Code Online (Sandbox Code Playgroud)
这里newWin只存在于此方法中; 它是在其中创建的,并且不会通过返回或分配给具有更宽范围的成员而离开方法的范围.
问很多人什么时候newWin收集垃圾,他们会告诉你它会在排队之后发生this.stillDontCare,因为那是在newWin超出范围的时候.因此,我们可以通过newWin = null在最后一次使用后分配获得轻微的胜利,但它可能可以忽略不计.
从概念上讲,这是事实,因为我们可以添加在newWin任何地方处理的代码,直到那时,newWin我们可以使用.
事实上,很可能很快就有newWin资格收藏.Show().虽然它在概念上处于范围之后,但它实际上并未使用,编译器知道这一点.(从现在开始,通过"编译器",我将指的是产生实际运行代码的整个过程,结合IL编译器和抖动).由于newWin不再使用自身使用的内存(即堆栈上的引用,而不是对象),编译器可以使用该内存irrelevant或其他内容.没有实时参考,该对象有资格收集.
实际上,如果调用对象的最后几个方法实际上并不使用this指针(无论是直接使用还是使用成员字段),那么甚至可以在调用这些方法之前收集对象,因为它们实际上并没有使用宾语.如果你有一个方法,其this指针从未被使用(再次,直接或间接),那么它可能永远不会被创建!
现在,考虑到这一点,我们可以看到,如果我们在变量超出范围之前将变量赋值为null,那么它实际上不会产生它似乎会产生的微小的可忽略的差异.
实际上,这可能使得赋值甚至可能需要更长时间才能符合条件,因为如果编译器无法看到变量的使用不会影响对象(不太可能,但可能会发生,如果存在try...catch...finally阻碍使分析更复杂的块,然后它甚至可以延迟对象被认为合格的点.这可能是微不足道的,但它就在那里.
到目前为止这么简单; 如果我们独自离开,就会发生好事,而单独离开很容易.
然而,可以将引用设置为null.考虑:
public class SomeClass
{
private WorkerThing _newWin;
private void DoStuff()
{
_newWin = new WinWorkers_AddWorker();
_newWin.WindowState = this.WindowState;
_newWin.Show();
}
}
Run Code Online (Sandbox Code Playgroud)
这里考虑一下,这次DoStuff()调用之后,_newWin存储在一个成员变量中.在范围超出范围之前,它不会SomeClass超出范围.什么时候会发生?
好吧,我无法回答这个问题,但有时答案很重要.如果它SomeClass本身也是短命的,那么谁在乎呢.它很快就会超出范围,_newWin随之而来.但是,如果我们分配_newWin = null了该对象,则该对象将立即有资格进行收集.
现在,一些重要的警告:
_newWin成为成员变量.如果上面的例子是完整的代码,我们会把它移回到本地,DoStuff()并且不仅以这种效率方式获得,而且更重要的是我们正确的机会,因为我们不能_newWin从另一个成员做一些愚蠢的事情.因此,将null赋给成员变量的主要原因仅仅是因为null已成为最合适的值.将null分配给不再使用的成员通常不会尽快释放其内存,而是因为它不再适合使用,并且这变得不可能 - 并且明确地向其他代码发出信号 - 当它发生时一片空白.
如果一个引用比一个方法寿命更长(因此放入一个成员变量)并且比包含对象的寿命短得多并且消耗了大量的内存,那么分配null就可能开始有意义了. .在发生这种组合的极少数情况下,我们可能希望将它指定为null以表明它不再适用于该类仍然存在,因此我们仍然不会指定null 以将其释放到GC.这几乎是可能的,但真的是"不".