GC.SuppressFinalize?

R

Rainer Queck

Hi NG,

I am not sure to evaluate what happens if I call the
GC.SuppressFinalize(this) for a object.
My question is:
In case I call GC.SuppressFinalize(this) from with in one of my object, do I
then have to somehow - if yes how - release instances created in the
constructor manuelly?

Simplified example:

public class TestObject
{
private List<string> strList;
public TestObject()
{
strList = new List<string>();
}

public void Dispose()
{
<releas my hw>
GC.GC.SuppressFinalize(this);
}
}

Would this code mean, that I have to "release" strList within my dispose or
will GC still take care of strList?

Note : I know, that this way of handling dispose is not complete.
I just extracted some code from the "DisposeExample" from
http://msdn.microsoft.com/library/d...l/frlrfsystemgcclasssuppressfinalizetopic.asp

Regards
Rainer
 
T

Tom Porterfield

Rainer said:
I am not sure to evaluate what happens if I call the
GC.SuppressFinalize(this) for a object.
My question is:
In case I call GC.SuppressFinalize(this) from with in one of my object,
do I then have to somehow - if yes how - release instances created in the
constructor manuelly?

Simplified example:

public class TestObject
{
private List<string> strList;
public TestObject()
{
strList = new List<string>();
}

public void Dispose()
{
<releas my hw>
GC.GC.SuppressFinalize(this);
}
}

Would this code mean, that I have to "release" strList within my dispose
or will GC still take care of strList?

Note : I know, that this way of handling dispose is not complete.
I just extracted some code from the "DisposeExample" from
http://msdn.microsoft.com/library/d...l/frlrfsystemgcclasssuppressfinalizetopic.asp

The point of this type of dispose implementation is that you have taken care
to free any resources that need to be freed in your Dispose method and
therefore there is no need to call your Finalizer. That doesn't mean you
shouldn't code a Finalizer that also releases any resources that you are
holding (ideally by calling the same method that your public Dispose calls
but with a switch to indicate where it is being called from), but it
indicates to the garbage collector that it does not need to explicitly call
your Finalize since your internal resources have already been released by
your Dispose method. Having a Finalize method gives the GC the chance to
get into your resource freeing method in the event that someone forgets to
call your Dispose method.

In your specific example, I don't think there is anything you need to do, so
would question why you are implementing a dispose pattern at all. Your
List<string> will be handled by the GC as those are managed resources that
don't have to be taken care of by you (what are you going to do in your
Dispose with the strList to release those resosurce?).

Implementing IDisposable when there is no reason to do so usually isn't good
practice.
 
D

Dustin Campbell

I am not sure to evaluate what happens if I call the
GC.SuppressFinalize(this) for a object.
My question is:
In case I call GC.SuppressFinalize(this) from with in one of my
object, do I
then have to somehow - if yes how - release instances created in the
constructor manuelly?
Simplified example:

public class TestObject
{
private List<string> strList;
public TestObject()
{
strList = new List<string>();
}
public void Dispose()
{
<releas my hw>
GC.GC.SuppressFinalize(this);
}
}
Would this code mean, that I have to "release" strList within my
dispose or will GC still take care of strList?

GC will still take care of strList. The only difference is that TestObject's
Finalize method won't be called. And, since TestObject doesn't actually override
the Object.Finalize method (using the destructor syntax), there's no need
to call GC.SuppressFinalize in the code that you posted. GC.SuppressFinalize(this)
will essentially do nothing in the code you posted.

Here's what happens when you override the Finalize method (or in C#, declare
a destructor). This will help explain the situation where calling GC.SuppressFinalize
is necessary.

When an object is allocated that overrides the Finalize method, a pointer
to the object is placed in a special 'finalization' queue. When the garbage
collector sees that the object can be reclaimed, it scans the finalization
queue and finds that a pointer to the object exists in the queue. The GC
then removes the pointer from the 'finalization' queue and adds it to the
'freachable' queue. The object actually survives the GC because the Finalize
method hasn't been called yet. There is a special thread in the runtime for
calling Finalize methods. When a pointer appears in the freachable queue,
this thread wakes up and calls the Finalize methods of the objects in the
queue. After this is done, the freachable queue is empty and the next GC
will reclaim the object (unless the object is resurrected in some way by
its Finalize method).

The net result of all of this is that, relying on the Finalize method can
have some unwanted side effects -- not the least of which is performance.
Enter the GC.SuppressFinalize method. When this is called, it ensures that
the Finalize method of the specified object is not called. So, the object
will be reclaimed on GC and not moved to the freachable queue. This makes
it particularly when implementing IDisposable.

FWIW, here is an abstract class that I use as a base IDisposable implementation:

public abstract class DisposableObject: IDisposable
{
private enum DisposeState { NotDisposed, Disposing, Disposed }

private DisposeState m_State = DisposeState.NotDisposed;
private object m_StateLock = new object();

~DisposableObject() // overrides Object.Finalize()
{
InnerDispose(false);
}

private void InnerDispose(bool disposing)
{
lock (m_StateLock)
{
if (m_State != DisposeState.NotDisposed)
return;

m_State = DisposeState.Disposing;
try
{
Dispose(disposing);
}
finally
{
m_State = DisposeState.Disposed;
}
}
}

protected abstract void Dispose(bool disposing);

public void Dispose()
{
InnerDispose(true);
GC.SuppressFinalize(this); // Finalize method will no longer be called.
}
}

Note that this class ensures that two threads cannot cause the object to
be disposed more than once. When overridding the Dispose(bool disposing)
method, make sure to check the 'disposing' parameter. If this is true, it
is called on the same thread that Dispose() was called on. If it is false,
it is being called from the runtime's finalizer thread that calls Finalize
methods.

Best Regards,
Dustin Campbell
Developer Express Inc
 
J

Jeffrey Tan[MSFT]

Hi Rainer,

Since you are implementing Dispose() method for your class, I assume you
are implementing IDisposable.Dispose() method.

IDisposable interface is only used to explicitly release unmanaged resource
such as file handle, bitmap resource or other OS unmanaged resource. This
is because .Net knows nothing about unmanaged resource in your class, you
should implement IDisposable.Dispose() method to free the unmanaged
resource. However, it is not used to dispose managed resource such as .Net
object memory because .Net GC will take care of releasing it.

In your scenario, if you are only concerning List<string> object in your
class, there is no need to implement IDisposable interface for it.

The article below talks more about when and how to use Dispose in C#:
"When and How to Use Dispose and Finalize in C#"
http://www.devx.com/dotnet/Article/33167/1954?pf=true

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
R

Rainer Queck

Hi Tom, Mark, Dustin and Jeffrey,

thanks for your hints and information.

Good to hear, that GC still takes care of my strList so that I can use the
Dispose pattern as basically shown in my example.
I do need this pattern since <my hardware> is a unmanaged recource I have to
take care of.

Regards
Rainer
 
J

Jeffrey Tan[MSFT]

Hi Rainer,

Glad to hear our replies make sense to you. If you need further information
regarding the GC topic, the best resource is the articles from "Jeffrey
Richter":
"Garbage Collection: Automatic Memory Management in the Microsoft .NET
Framework"
http://msdn.microsoft.com/msdnmag/issues/1100/gci/

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top