但我不确定这第二个案件的处理方式是否与第一个案件相同。 完全是一个单独的问题。只是因为你实现了 IDispose,这并不意味着该对象不再需要GC。 如果你有IDispose,那就意味着你需要通过调用执行 IDispose的Dispose方法以某种方式管理 对象的生命周期。实现IDispose通常有两个原因。 第一个,也是最常见的,因为实例正在坚持使用某些非托管资源来支付,而你需要尽快释放它。 在这种情况下实现IDispose时,你还需要实现一个 终结器(析构函数,尽管术语不正确,IMO) 。如果人们不打电话给Dispose,那么终结者 就是一个安全保障。如果还没有完成,它将基本上释放非托管资源。 终结是一个昂贵的过程。该对象基本上是 重新确定并放置在终结队列中,然后执行终结器 。如果在一个对象上调用Dispose,则不需要确定,这就是为什么你在Dispose的 实现中看到对GC.SuppressFinalize的调用。 ,而不是终结者本身。由于 终结器和Dispose做同样的事情,如果调用Dispose,你可以有效地告诉GC不要敲定你,并避免代价高昂的开销。 /> 但是,即使你说你要压制终结, 对象仍然需要进行GCed。即使在调用Dispose时,仍然必须在此对象上发生回收内存 的过程。然而, 它是你真正不在乎的东西,因为它只是记忆,而你已经放弃了对它的控制(对于大部分)同意在 CLR中运行(这是GC的目的,担心这些事情,而不是你的)。 禁止终结只意味着终结者不会被调用,它不会意味着对象已被GC。 使用的第二个原因IDispose是因为你需要一些确定性的 终结。例如,在方法中的操作之后,您可能总是需要设置一些 变量。在这种情况下,生成一个实现IDisposable的类可能是一个好主意,因为你可以在退出using块时将恢复为变量(而不是 显式记住编写try / catch / finally块代码。 在你的情况下,你属于使用IDispose的第一个类别。 如果你真的有一个 非托管资源,那么使用using语句将非常重要。如果你没有,并且它只是一个 常规类,那么使用using语句将无法工作,并且实现IDispose的也无济于事。 希望这会有所帮助。 - - Nicholas Paldino [.NET / C#MVP] - mv*@spam.guard.caspershouse.com 任何建议/想法都将是非常感谢! Thnak you, Andrey Lately i''ve been (and still am) fixing some memory leaks problems in the project i just took over when i got this new job. Among the other issues i''ve noticed that for localy created objects it makes difference to explicitly put them to null after working with them is done - it somehow makes the GC collect them sooner, like here: void SomeFunc() { MyClass c = new MyClass(); c.CallSomeOtherFunc(); c = null; }This depends on how it is compiled. If you are compiling in debug mode,then yes, it will make it GC faster (although how much faster isquestionable since c would have been released very quickly afterwards, dueto exiting the method). The reason for this is that code compiled in debugmode will not have references released when they are no longer used. Whencompiled for release mode, however, you are actually ^extending^ thelifetime of your object with the "c = null" assignment. If the statementwas not there, the compiler would realize that the object pointed to by c isno longer needed after the call to CallSomeOtherFunc (unless the referencepointed to by c is stored somewhere else in the call to CallSomeOtherFunc),and then set it to null, allowing it to become eligible for GC.However, with the "c = null" statement, the compiler realizes (althoughI don''t know if agressive optimizations here can pick it up) that it isneeded for another call, and the object pointed to by c isn''t made eligibleuntil ^after^ the assignment. If i don''t put "c" to null time to get it collected is way longer than if i explicitly dereference the object. It''s really strange, as it''s obvoius that object''s lifetime is limited by body of "SomeFunc".This isn''t true. GCs are not pre-determined. Why a GC occurs veryquickly in one run of the app as opposed to very late in another run of theapp is not easily determinable. There are other factors outside yourapplication which can force a GC as well. The timing of one GC in one runof the app vs a GC of another run in an app means very little. But anyway, my question is: is there any difference in the first example compared to this: void SomeFunc() { using (MyClass c = new MyClass()) { c.CallSomeOtherFunc(); } } The second way looks nicer for me and avoids forgetting to explicitly dereference the object, but i''m not sure if this second case is being treated the same way as the first one.This is a separate issue completely. Just because you implementIDispose, it doesn''t mean that the object doesn''t need to be GCed anymore.If you have IDispose, it means that you need to manage the lifetime of theobject in some way by calling the Dispose method on the implementation ofIDispose. There are usually two reasons you implement IDispose.The first, and most common, is because the instance is holding on tosome unmanaged resource, and you need to release it as soon as possible.When implementing IDispose in this scenario, you also need to implement afinalizer (destructor, although the term is incorrect, IMO). The finalizeris meant to be a safeguard if people don''t call Dispose. It will basicallyrelease the unmanaged resource if it hasn''t been done already.Finalization is an expensive process. The object is basicallyressurected and placed in a finalization queue, and then has the finalizerexecuted. If Dispose is called on an object, it doesn''t need to befinalized, which is why you see a call to GC.SuppressFinalize in theimplementation of Dispose, and not the finalizer itself. Since thefinalizer and Dispose do the same thing, if Dispose is called, you caneffectively tell the GC to not finalize you, and avoid that costly overhead.However, even if you say that you are going to suppress finalization,the object still has to be GCed. The process of having the memory reclaimedstill has to occur on this object, even when Dispose is called. However,it''s something you really don''t care about, because it''s just memory, andyou gave up control of that (for the most part) by agreeing to run in theCLR (that''s the purpose of the GC, to worry about these things, not yours).Suppressing finalization only means the finalizer will not be called, itdoesn''t mean that the object has been GCed.The second reason to use IDispose is because you need some deterministicfinalization to take place. For example, you might always need somevariable set back after an operation in a method. In this case generating aclass which implements IDisposable might be a good idea, since you canrevert the variable back when the using block is exited (instead of havingto explicitly remembering to code a try/catch/finally block).In your case, you fall into the first category for using IDispose.Using the using statement will be important, if you actually have anunmanaged resource you are holding on to. If you do not, and it is just aregular class, then using the using statement will not work, andimplementing IDispose will not help either.Hope this helps.--- Nicholas Paldino [.NET/C# MVP]- mv*@spam.guard.caspershouse.com Any suggestions/ideas would be highly appreciated! Thnak you, Andrey Tom Porterfield写道:Tom Porterfield wrote:在2005年2月17日星期四10:02:52 -0500,MuZZy写道: On Thu, 17 Feb 2005 10:02:52 -0500, MuZZy wrote:最近我一直(并且仍在)解决一些内存泄漏问题当我得到这份新工作时,我接手了这个项目。在其他问题中,我注意到对于localy创建的对象,在使用它们之后明确地将它们置为null是不同的 - 它以某种方式使得GC更快地收集它们,就像这里: void SomeFunc() { MyClass c = new MyClass(); c.CallSomeOtherFunc(); c = null; } 如果我不放c如果我明确地取消引用对象,那么将时间收集起来的时间要长一些。这真的很奇怪,因为对象'的生命周期受到SomeFunc主体的限制。但无论如何,我的问题是:第一个例子与此相比有什么不同: void SomeFunc() {使用(MyClass c = new MyClass()) c.CallSomeOtherFunc(); } } 第二种方式看起来更好,避免忘记明确取消引用对象,Lately i''ve been (and still am) fixing some memory leaks problems in the project i just took overwhen i got this new job. Among the other issues i''ve noticed that for localy created objects itmakes difference to explicitly put them to null after working with them is done - it somehow makesthe GC collect them sooner, like here:void SomeFunc(){MyClass c = new MyClass();c.CallSomeOtherFunc();c = null;}If i don''t put "c" to null time to get it collected is way longer than if i explicitly dereferencethe object. It''s really strange, as it''s obvoius that object''s lifetime is limited by body of"SomeFunc". But anyway, my question is: is there any difference in the first example compared to this:void SomeFunc(){using (MyClass c = new MyClass()){c.CallSomeOtherFunc();}}The second way looks nicer for me and avoids forgetting to explicitly dereference the object,but i''m not sure if this second case is being treated the same way as the first one. 你的第二种情况与第一种情况不同。另一种写的方法是: void SomeFunc() { MyClass c = new MyClass()尝试 { c.CallSomeOtherFunc(); } 终于 { c.Dispose(); } } 所以在你的第一个例子中,你将c设置为null,然后才会超出范围。在你的第二个例子中,你没有将c设置为null,但是你保证无论发生什么都会调用c.Dispose()。 Your second case is not the same as the first. Another way to write the second would be: void SomeFunc() { MyClass c = new MyClass() try { c.CallSomeOtherFunc(); } finally { c.Dispose(); } } So in your first example you are setting c to null before it goes out of scope. In your second example you are not setting c to null, but you are guaranteeing that c.Dispose() will be called no matter what happens. 谢谢! 所以如果我更关心较短的物体寿命,我宁愿这样做: void SomeFunc() { MyClass c = new MyClass() c.CallSomeOtherFunc(); c.Dispose(); c = null; } 比使用使用? 对吗? br />Thank you!So if i''m more concerned about shorter object lifetime, i''d rather do this:void SomeFunc(){MyClass c = new MyClass()c.CallSomeOtherFunc();c.Dispose();c = null;}than use "using"?Right? 这篇关于"使用" vs" = null"和对象的生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-16 01:17