|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
SuppressFinalize in Dispose confusionMy class has a Socket member, so FxCop complained that my class needs to implement IDispose. Documentation says that either Dispose or the finalizer (destructor?) get called, but never both. Is that because the examples have SuppressFinalize being called in Dispose? In my attempt to follow the examples, I've got a destructor that calls Dispose(false), a Dispose() that calls Dispose(true) and GC.SupressFinalize(this), and a Dispose(bool) that looks like: protected virtual void Dispose( Boolean disposing) { if (! disposed) { if (disposing) { if (listenerSocket != null) { listenerSocket.Close(); listenerSocket = null; } } disposed = true; } } First of all, is this right? Next, I'm confused about SuppressFinalize being called in Dispose(). My class has other object members. Does my Dispose(bool) need to set them all to null in order for them to get cleaned up by garbage collection? If not, when are they available for collection? I'm also confused about the examples. In the SuppressFinalize documentation (ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref2/html/M_System_GC_SuppressFinalize_1_b4c5a2da.htm), for example, in the Dispose(bool disposing) function, it says to dispose of managed resources only if disposing is true, but to dispose of unmanaged resource regardless of the value of disposing. Socket is managed, but isn't it IDisposable because it manipulates an unmanaged resource? So should I call Socket's Close only if disposing is true, or regardless? By the way, I'm supposed to call Close, right? I thought I was supposed to call Socket's Dispose, but that's protected. Thanks. I also see that FxCop says:
If the type does not own any unmanaged resources, do not implement a finalizer on it. This goes to my question about Socket. It's a managed type, but isn't the reason it's IDisposable because it contains an unmanaged type? So, should my class that contains a Socket member have a destructor (that calls Dispose(false)) or not? Thanks uncaged <unca***@discussions.microsoft.com> wrote:
> I also see that FxCop says: Nope. Unless you hold onto the resources *directly*, you don't need to > > If the type does not own any unmanaged resources, do not implement a > finalizer on it. > > This goes to my question about Socket. It's a managed type, but isn't the > reason it's IDisposable because it contains an unmanaged type? So, should my > class that contains a Socket member have a destructor (that calls > Dispose(false)) or not? have a finalizer. Instead, Socket (or whatever it uses to hold onto the handle) should have the finalizer. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too Thanks !
Show quote "Jon Skeet [C# MVP]" wrote: > uncaged <unca***@discussions.microsoft.com> wrote: > > I also see that FxCop says: > > > > If the type does not own any unmanaged resources, do not implement a > > finalizer on it. > > > > This goes to my question about Socket. It's a managed type, but isn't the > > reason it's IDisposable because it contains an unmanaged type? So, should my > > class that contains a Socket member have a destructor (that calls > > Dispose(false)) or not? > > Nope. Unless you hold onto the resources *directly*, you don't need to > have a finalizer. Instead, Socket (or whatever it uses to hold onto the > handle) should have the finalizer. > > -- > Jon Skeet - <sk***@pobox.com> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too > Inline.
uncaged wrote: Show quote > I'm confused about using SuppressFinalize in Dispose. Yes. It looks fine to me. You probably don't need to set> > My class has a Socket member, so FxCop complained that my class needs to > implement IDispose. > > Documentation says that either Dispose or the finalizer (destructor?) get > called, but never both. Is that because the examples have SuppressFinalize > being called in Dispose? > > In my attempt to follow the examples, I've got a destructor that calls > Dispose(false), a Dispose() that calls Dispose(true) and > GC.SupressFinalize(this), and a Dispose(bool) that looks like: > > protected virtual void Dispose( Boolean disposing) > { > if (! disposed) > { > if (disposing) > { > if (listenerSocket != null) > { > listenerSocket.Close(); > listenerSocket = null; > } > } > disposed = true; > } > } > > First of all, is this right? > listenerSocket = null in this particular case, but it's not a big deal. > Next, I'm confused about SuppressFinalize being called in Dispose(). My Well, techically yes. But I think you're thinking about this the wrong> class has other object members. Does my Dispose(bool) need to set them all > to null in order for them to get cleaned up by garbage collection? way. In most use cases an object is no longer referenced after its Dispose method has been called. If it's no longer referenced then it, along with its associated object graph, are all eligible for collection. That's why setting listenerSocket = null is usually not needed. >If not, when are they available for collection? They are available for collection whenever the GC cannot find a> reference to them. Now, if you continue to hold a reference to your class after calling Dispose then the other objects referenced inside your class will not be eligible for collection either. However, the Socket will be eligible since you explicitly set its reference to null inside the Dispose(bool) method. > I'm also confused about the examples. In the SuppressFinalize documentation Yes. It is a managed object that holds unmanaged resources. Since it> (ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref2/html/M_System_GC_SuppressFinalize_1_b4c5a2da.htm), > for example, in the Dispose(bool disposing) function, it says to dispose of > managed resources only if disposing is true, but to dispose of unmanaged > resource regardless of the value of disposing. Socket is managed, but isn't > it IDisposable because it manipulates an unmanaged resource? is a managed object only call it's Dispose (Close) method when disposing is true. It doesn't appear that your class holds unmanaged resources *directly* so there's nothing else you need to do. > So should I Call Socket.Close or Socket.Dispose only if disposing is true. If> call Socket's Close only if disposing is true, or regardless? disposing is false then the GC called the Dispose(bool) method and that means managed object references may not be valid. In other words, the GC may have already called the Socket's Finalize method because the order in which the GC calls Finalize is unpredictable. > By the way, Calling Close is usually fine. The Dispose method is public. You're> I'm supposed to call Close, right? I thought I was supposed to call Socket's > Dispose, but that's protected. > just not seeing it because it's implemented explicitly. You call it by casting it into an IDisposable reference. Show quote > Thanks. Thanks, that was very helpful.
Show quote "Brian Gideon" wrote: > Inline. > > uncaged wrote: > > I'm confused about using SuppressFinalize in Dispose. > > > > My class has a Socket member, so FxCop complained that my class needs to > > implement IDispose. > > > > Documentation says that either Dispose or the finalizer (destructor?) get > > called, but never both. Is that because the examples have SuppressFinalize > > being called in Dispose? > > > > In my attempt to follow the examples, I've got a destructor that calls > > Dispose(false), a Dispose() that calls Dispose(true) and > > GC.SupressFinalize(this), and a Dispose(bool) that looks like: > > > > protected virtual void Dispose( Boolean disposing) > > { > > if (! disposed) > > { > > if (disposing) > > { > > if (listenerSocket != null) > > { > > listenerSocket.Close(); > > listenerSocket = null; > > } > > } > > disposed = true; > > } > > } > > > > First of all, is this right? > > > > Yes. It looks fine to me. You probably don't need to set > listenerSocket = null in this particular case, but it's not a big deal. > > > Next, I'm confused about SuppressFinalize being called in Dispose(). My > > class has other object members. Does my Dispose(bool) need to set them all > > to null in order for them to get cleaned up by garbage collection? > > Well, techically yes. But I think you're thinking about this the wrong > way. In most use cases an object is no longer referenced after its > Dispose method has been called. If it's no longer referenced then it, > along with its associated object graph, are all eligible for > collection. That's why setting listenerSocket = null is usually not > needed. > > >If not, when are they available for collection? > > > > They are available for collection whenever the GC cannot find a > reference to them. Now, if you continue to hold a reference to your > class after calling Dispose then the other objects referenced inside > your class will not be eligible for collection either. However, the > Socket will be eligible since you explicitly set its reference to null > inside the Dispose(bool) method. > > > I'm also confused about the examples. In the SuppressFinalize documentation > > (ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref2/html/M_System_GC_SuppressFinalize_1_b4c5a2da.htm), > > for example, in the Dispose(bool disposing) function, it says to dispose of > > managed resources only if disposing is true, but to dispose of unmanaged > > resource regardless of the value of disposing. Socket is managed, but isn't > > it IDisposable because it manipulates an unmanaged resource? > > Yes. It is a managed object that holds unmanaged resources. Since it > is a managed object only call it's Dispose (Close) method when > disposing is true. It doesn't appear that your class holds unmanaged > resources *directly* so there's nothing else you need to do. > > > So should I > > call Socket's Close only if disposing is true, or regardless? > > Call Socket.Close or Socket.Dispose only if disposing is true. If > disposing is false then the GC called the Dispose(bool) method and that > means managed object references may not be valid. In other words, the > GC may have already called the Socket's Finalize method because the > order in which the GC calls Finalize is unpredictable. > > > By the way, > > I'm supposed to call Close, right? I thought I was supposed to call Socket's > > Dispose, but that's protected. > > > > Calling Close is usually fine. The Dispose method is public. You're > just not seeing it because it's implemented explicitly. You call it by > casting it into an IDisposable reference. > > > Thanks. > > To clarify one point:
1. You need to implement IDisposable because the only thing that will call Dispose() on your socket is your class. If you dont implement it or nobody calls it then the socket will not be closed until the GC runs its finalizer which is usually later than you would want. 2. You don't need to implement a finalizer because the GC will call the finalizer of the socket when it collects it. In fact even if you had a finalizer it should not touch the socket because the GC can collect and finalize the socket BEFORE finalizing the object that references it. 3. You suppress finalization after disposing as an optimization because there is an associated overhead (it keeps the object around longer than necessary) Show quote "uncaged" <unca***@discussions.microsoft.com> wrote in message news:9248E879-BBE5-46A2-AA75-CADCD7616620@microsoft.com... > I'm confused about using SuppressFinalize in Dispose. > > My class has a Socket member, so FxCop complained that my class needs to > implement IDispose. > > Documentation says that either Dispose or the finalizer (destructor?) get > called, but never both. Is that because the examples have > SuppressFinalize > being called in Dispose? > > In my attempt to follow the examples, I've got a destructor that calls > Dispose(false), a Dispose() that calls Dispose(true) and > GC.SupressFinalize(this), and a Dispose(bool) that looks like: > > protected virtual void Dispose( Boolean disposing) > { > if (! disposed) > { > if (disposing) > { > if (listenerSocket != null) > { > listenerSocket.Close(); > listenerSocket = null; > } > } > disposed = true; > } > } > > First of all, is this right? > > Next, I'm confused about SuppressFinalize being called in Dispose(). My > class has other object members. Does my Dispose(bool) need to set them > all > to null in order for them to get cleaned up by garbage collection? If > not, > when are they available for collection? > > I'm also confused about the examples. In the SuppressFinalize > documentation > (ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/cpref2/html/M_System_GC_SuppressFinalize_1_b4c5a2da.htm), > for example, in the Dispose(bool disposing) function, it says to dispose > of > managed resources only if disposing is true, but to dispose of unmanaged > resource regardless of the value of disposing. Socket is managed, but > isn't > it IDisposable because it manipulates an unmanaged resource? So should I > call Socket's Close only if disposing is true, or regardless? By the way, > I'm supposed to call Close, right? I thought I was supposed to call > Socket's > Dispose, but that's protected. > > Thanks. > Nick Hounsome <nh***@nickhounsome.me.uk> wrote:
<snip - I agree with most of the post> > 2. You don't need to implement a finalizer because the GC will call the Not quite - it can finalize the socket, but it can't collect it. If the > finalizer of the socket when it collects it. > In fact even if you had a finalizer it should not touch the socket because > the GC can collect and finalize the socket BEFORE finalizing the object that > references it. referring object resurrects itself (eg assigning a reference to "this" to a static field somewhere) then the socket object would have to be kept alive too. It may well have been finalized before this, however, in which case I wouldn't expect it to behave terribly nicely... -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too |
|||||||||||||||||||||||