Simple destructor issue (IDisposable interface) - c#

I am a beginner in C#, I don't know why this isn't working, I just want to set this object to null by calling Dispose() method.
Why this is not possible?
class MyClass:IDisposable
{
public void Dispose()
{
this = null;
}
}

The purpose of the Dispose method isn't to clean up that class, but to clean up the disposable dependencies that the class is holding on to so that it can be disposed of normally by the garbage collector.
I'd suggest reading up more on the Dispose pattern and how to implement it in C#.
A bit of pedantry: The Dispose method is not a destructor, nor is it a finalizer.

Your question really seems to boild down to 'How do I delete stuff in C#'. The short answer is you can't, that's the job of the Garbage Collector System.GC. The IDisposable inerface is used to ensure that imporant resources that don't belong to .Net (like files, or network/database connections, but not a .Net class), are cleaned up on demand.
The IDisposable interface is important because it allows you to use the using pattern. That is, if your class implements IDisposable it can be used in a using block. Consider for instance:
class MyClass : IDisposable {
public void Dispose() { }
}
this class can now be used like this:
using (MyClass instance = new MyClass())
{
} // instance.Dispose() is called here at the end of the block.
The point of the using block is that when the block ends, it the compiler will throw in a call to Dispose() which you can use to get rid of important resources like files and database connections. For example, all of the Stream classes, like FileStream and what not implement IDisposable because it's a bad idea to leave a file open. Instead, you wrap all of your access in a using block, and then you are guaranteed that FileStream.Dispose will close the file out. Consider:
using (FileStream myFile = File.OpenRead("..."))
{
// Read the content of the file.
} // The file is guaranteed to be closed here. Cool!
This is much neater than doing something like this:
FileStream stream = File.OpenRead(" ... ");
stream.Close(); // Yes, you closed it manually, but it's error prone. What if you forget to do this?
Now what you're thinking of is a term called "Finalization", that is when the class is actually destroyed. This happens when the garbage collector (the System.GC class) actually destroys objects and cleans up their memory. Consider:
public class MyClass {
// This method, the 'Finalizer' will be called when the class is destroyed.
// The 'finalizer' is essentially just the name of the class with a '~' in front.
~MyClass() {
Console.WriteLine("Destroyed!");
}
}
public class Program {
public static void Main() {
MyClass referenceHeld = new MyClass(); // Reference held
new MyClass(); // No reference held on this class
WeakReference sameAsNoReference = new WeakReference(new MyClass()); // Equivalent to no reference.
System.GC.Collect(); // Force the garbage collector to collect
Console.ReadLine();
}
}
In short, the Garbage collector is the part of the runtime that cleans up stuff that isn't being used. What does it mean to not be used? It means that there are no references attached to the object. For example, if you run the program above, you'll notice that the word "Destroyed" gets printed on the screen twice. That's because two of the instances of MyClass created in the Main function are not pointed to by reference (A WeakReference is essentially the same thing as no reference). When we call GC.Collect() the garbage collector runs and cleans up the references.
That said, you should NOT call GC.Collect on your own. You can, for experimentation and education of course, but most people will tell you that the garbage collector does a fine job of keeping things clean on it's own. It doesn't make sense to have a bunch of GC.Collect scattered throughout your code, because that's the whole point of having a Garbage collector - to not have to worry about cleaning things up yourself.
So in short, you really can't destroy objects on your own, unless you call GC.Collect() (which you shouldn't do). The IDisposable interface allows you to work with the using pattern, ensuring that important resources are released (This is not the same thing as destroying the object though! All IDisposable does is ensure that Dispose() is called when the using block exits so you can clean up important stuff, but the object is still alive - an important distinction).

A class cannot make itself null because it has no control of who is referencing it.
For example, if you have a variable with an object in your code, that object cannot make itself null in YOUR code, it can only set it's OWN members to null.
In addition to this, think of a case where multiple classes reference the same object, where would he be null?
This is the kind of things the containing class should do.

The simple answer is that the "this" keyword is read only and can't be set.
A longer more fundamental answer is that you can't set objects themselves to null in c#, however you can set the reference to an object to null. When you set an object's reference to null and nothing else references that object, that is when the object is in a state to be garbage collected. (This is a simplification of what actually occurs.)
For example:
Object oTest = new Object;
oTest = null;
In the example above the object still exists after its reference oTest has been set to null. Its simply waiting for the garbage collector to come around and delete it.
So in your code it looks like your trying to set all of your references to your object equal to null, even if that may not be what your intending. This can't be done from the object itself. You need to make sure that all of the reference to your object are manually set to null or they are guaranteed to leave scope in your program.
null (C# Reference)
this (C# Reference)

You cannot modify your this pointer. In your example, your Dispose method doesn't need to do anything, so could be omitted altogether (along with updating the class to no longer implement IDisposable)

Dispose pattern is only needed when you use non-CLR resources, like graphics contexts or low level io. There are edge cases when you need to free up resources now, but as you say you are a beginner you really should not bother (yet).
Setting this to nil does not help. Consider this
MyClass sample = new MyClass();
sample.Dispose();
// at this point, sample still has a value
When you want to get rid of an object in C#, all you need is to let all the references go out of scope, or set them to nil. (Multiple variables can refer to the same instance). The runtime will free the object (and its subobjects) automatically because nobody is using it anymore.
Roughly speaking, you can think of them as pointers (technically they are not, but we are trying to explain the principle here)

Related

How to dispose object

How to dispose my object? I am doing it by this. Whats is wrong? The Obj.Dispose() function does not appear to be right.
class MainclassForm : Form, IDisposeable
{
public void createanddispose()
{
A obj = new A();
obj.dowork();
obj.Dispose();//does not appear as a function
}
}
You can better use the using statement. Something like
using (MyIDisposableObject obj = new MyIDisposableObject())
{
// object here
}
A good reference to check on MSDN: Avoiding Problems with the Using Statement
The C# "using" statement results in a call to Dispose(). This is the
same as Close(), which may throw exceptions when a network error
occurs. Because the call to Dispose() happens implicitly at the
closing brace of the "using" block, this source of exceptions is
likely to go unnoticed both by people writing the code and reading the
code. This represents a potential source of application errors.
To call Dispose() on an object, your class must be inherited from IDisposeable interface and have an implementation of it:
class A : IDisposable
{
public void Dispose()
{
GC.Collect();
}
}
There are a couple things wrong here, but I believe the root is that you might confusing IDisposable with a Garbage Collector.
IDisposable is an interface that the type A, in your example, may implement. It that were the case, you could be sure that any instance of A had the method Dispose() you're looking for. This is useful for things like Streams, where they need to be closed, but it's not useful for (just as an example) a ComplexNumber type that has no outstanding resources.
In these cases, your managed C# code will handle all the "disposal" that needs to happen. It will get rid of the memory that object is using. That feature comes for free (sort of), and you don't need (or want) to do anything to explicitly invoke it. That's the main difference between managed (C#, Java, etc.) and unmanaged (C++) code.
Essentially, if an object is using more than just memory (like an open file does), IDisposable will be useful. If it is just memory (like a Form, or DateTime, or a majority of other things), there's no need for it.
As for your specific code, you've applied IDisposable to the type that contains your functions. Just as you couldn't call this.AddMinutes(1) to get at DateTime's method, you can't get at this one.
If you do need the added functionality of implementing IDisposable, you'll have to do it on A. Applying IDisposable, like any other interface, to MainclassForm will tell the compiler that you have a Dispose() method on that class, which is true only because the Windows Forms object has one. If it didn't, this would throw a compiler error, and you'd have to add one.

Where is the C# Destructor

I have a class that spawns another UI thread and does it's thing. I need to abort that thread and clean up whenever my parent class is destroyed. So how do I know when my parent class is destoryed?
Coming from C++ my first thought was to put this in the destructor. But C# doesn't really have any destructors - only finalizers and dispose - which from what I understand - may or may not be called (I guess it's a mood thing for the GC??).
That's great and simple - if you may or may not want to release your resources.
But where do you put code that ABSOLUTELY POSITIVELY MUST BE EXECUTED whenever an object is destroyed?
You put it in Dispose (implementing the IDisposable interface) and then ensure that Dispose is called when the object is no longer required. There's a language construct that does just this:
using (var foo = new Foo())
{
// Do something with foo.
}
foo.Dispose will be called at the end of the using block. This is equivalent to:
{
var foo = new Foo();
try
{
// Do something with foo.
}
finally
{
foo.Dispose();
}
}
Note that Dispose is not called automatically when the object leaves scope; you need to do it yourself, using either a using block or by calling it explicitly.
You should, however, provide a finalizer in Foo that calls Dispose, so that if the object isn't disposed before the GC gets to it, you aren't left with unreleased resources:
~Foo()
{
Dispose();
}
The idea behind the IDisposable pattern is that it tells you unambiguously when a class needs disposing. Here's an article that describes how to implement it properly (accounting for possible descendant classes).
There is no way to guarentee that something "ABSOLUTELY POSITIVELY [WILL] BE EXECUTED" when an object is destroy (try pulling the plug on your PC --- finalizers ain't gonna be called)
The best you can hope for is the finalizer -- defined in C# using C++ destructor syntax. Although, you be better off implementing IDisposable, and using a using{} block.
Although it is not common to use this method, you can define a "destructor" in C# by using the ~ character, like so:
class Parent
{
~Parent() // destructor
{
// cleanup statements...
}
}
Note:
The destructor implicitly calls Finalize on the base class of the
object.
(source)
You make your class a Component and the containing class a Container.
See: C# - What is a component and how is it typically used?
Other answers seem to be busy with "going out of scope" use case. But "whenever my parent class is destroyed"? If "parent class" is a "containing object", components are the right tool.

Will object with reference kept be disposed?

May I know if the "objectToBeDisposed" will be disposed if its reference are kept by the "useDisposableObject"?
using(IDisposable objectToBeDisposed = new ObjectImplementedIDisposable ()){
ChildObject useDisposableObject = new ChildObject(objectToBeDisposed);
.... doing stuff with useDisposableObject;
}
Yes, in your example it will be disposed, because the using block explicitly calls the Dispose() method when leaving that block.
As an aside the referencing object is within the using block scope and will go out of scope at the end of the using block, which will avoid the potential issue of accessing a disposed object if the referencing object tried to use it once it was disposed.
Update thanks to #dlev
Disposal, finalization and memory deallocation are 3 totally different things in the .NET world.
Disposal is only an "application logic" thing, it is implemented through the disposable pattern.
If you implement the interface IDisposable, your object can be used with the using keyword.
The using keyword will translate in a simple way:
using (IDisposable xxx = new MyObject())
{
....
}
means
{
IDisposable xxx = new MyObject();
try
{
....
}
finally
{
if (xxx != null)
xxx.Dispose();
}
}
There is no other magic in this. That's all.
Object finalization is instead called by garbage collector when the objects should be freed.
The time when it happens and the order between destructors is unpredictable.
class myclass { ~myclass() { this code will be called by garbage collector, i cannot call it } }
The syntax is very similar to C++ destructors but the meaning is a lot different.
And then memory deallocation.
Memory deallocation is not connected to object disposal!
You can keep forever a reference to a disposed object. Disposal is just something related to application logic.
Destructors can also be cancelled or called more than once by garbage collector (see GC.ReRegisterForFinalize and GC.SuppressFinalize).
The presence of a destructor in a class slow down a lot the garbage collector, and inside destructor, you can do almost nothing except releasing unmanaged resources.
Disposal instead as I said is an application thing, is just a method, and is not related to garbage collector.
"Disposing" an object has nothing to do with which references are kept around. IDisposable itself is just an interface, nothing more.
When a class implements that interface, a user of the class can call a public void Dispose() method on the object. When the user of the class places an instance of the class in a using block, the Dispose() method will automatically get called. When an Enumerator class implements IDisposable and is used in a foreach loop, it will also have Dispose() called on it.
This has absolutely nothing to do with which references are kept around, or the automatic garbage collection system.
However, IDisposable also has a design "contract" that goes with it. This contract is a pattern that classes that implement IDisposable must follow to have correct program behavior.
The contract is that once you've called Dispose(), you should never call any property or method on the object again, otherwise you should expect an ObjectDisposedException to be thrown. The only thing that is allowed to be called on that object after that point is Dispose() again, or the object finalizer (via garbage collection).
Because of this, people will sometimes set an reference to an IDisposable class to null after they have disposed it, so they don't accidentally call methods on the already-disposed object. If you placed the reference in a using block, you don't have to worry about this; The compiler won't even let you touch the reference again. If you try, you will get an error and your program will fail to compile.
This contract is not built into the language or CLR itself - it must manually be adhered to by the implementer of a class.
Yes, it will be. I might be wrong, but I don't think #John Weldon's explanation is not accurate though. You can only call using on an IDisposable implementing class, and when the using exits, it will call Dispose() on the object.
The part where I don't agree is the 'because the referencing object is within the using block scope and will go out of scope at the end of the using block' part. The objects declared in scope will not always be disposed of when the using exits. If you take this example
JustAClass myInstance = new JustAClass();
using ( MyDisposableClass theUsingInstance = new MyDisposableClass() )
{
AnotherClass innerInstance = new AnotherClass();
myInstance.ItsOtherClass = innerInstance;
myInstance.ItsWhatever = theUsingInstance;
}
At the end of this code, myInstance.ItsOtherClass is not null. innerInstance has been created in the using section and won't be garbage collected since there is still a referenced. However, the object refered by myInstance.ItsWhatever has been disposed of, since it's the using target.

Do I need to implement a dispose or finalize in my objects?

For too long I let the garbage collector do its magic, removing all responsibilities from my self.
Sadly it never turned into an issue... So I never gave a second thought to the subject.
Now when I think about it I don't really understand what the "dispose" function really does and how and when it should be implemented.
The same question for finalize...
And a last question...
I have a class pictureManipulation : when I need to save/resize/change format ... I start a new instance of that class use its objects and... well let the garbage collection kill the instance
class student
{
public void displayStudentPic()
{
PictureManipulation pm = new PictureManipulation();
this.studentPic = pm.loadStudentImage(id);
}
}
Class Test
{
student a = new Student();
a.displayStudentPic();
// Now the function execution is ended... does the pm object is dead? Will the GC will kill it?
}
Regarding your class Student
Do I need a Dispose() ?
Assuming the Picture class is IDisposable: Yes. Because a Student object 'owns' the studentPic and that makes it responsible for cleaning it up. A minimal implementation:
class Student : IDisposable
{
private PictureClass studentPic;
public void Dispose()
{
if (studentPic != null)
studentPic.Dispose();
}
...
}
And you now use a Student object like:
void Test
{
using (Student a = new Student())
{
a.displayStudentPic();
} // auto Dispose by using()
}
If you can't/don't use a using(){} block, simply call a.Dispose(); when you're done with it.
But please note that the (far) better design here would be to avoid keeping a picture object inside your Student object. That sets off a whole chain of responsibilities.
Do I need a Finalizer?
No. Because when a Student object is being collected, its studentPic object is guaranteed to be collected in the same run. A Finalizer (destructor) would be pointless but still expensive.
You only need to implement the Dispose method if your type holds some unmanaged resources like DB connections, file handles, etc. or if some of the objects that are held by your type implement the IDisposable interface. Here is a few points you should consider when implementing the standard Dispose pattern:
if your object doesn’t hold any IDisposable objects or unmanaged resources (DB connection, for example) then you don’t need to implement the IDisposable or finalizer at all
if your object holds references to IDisposable objects, then call Dispose() on these objects in the Dispose method
if your object doesn’t hold any unmanaged resources then don’t implement a finalizer, the Garbage Collector won’t attempt to finalize your object (which has a performance hit) unless you have implemented a finalizer.
if your object holds unmanaged resources, clean them up in the finalizer without re-writing any of the cleanup code in the Dispose(bool) method already.
You need to take care about object disposal if it holds resources other than just memory held by the object itself.
For instance, if your object abstracts a file, you must be in control when the file is released, or, you will mess things up very bad: your app finished using it and it will still be locked, until GC disposes your object.
To know how to do it properly, read manuals about dispose and finalize as well as the using(){} clause.

Who Disposes of an IDisposable public property?

If I have a SomeDisposableObject class which implements IDisposable:
class SomeDisposableObject : IDisposable
{
public void Dispose()
{
// Do some important disposal work.
}
}
And I have another class called AContainer, which has an instance of SomeDisposableObject as a public property:
class AContainer
{
SomeDisposableObject m_someObject = new SomeDisposableObject();
public SomeDisposableObject SomeObject
{
get { return m_someObject; }
set { m_someObject = value; }
}
}
Then FxCop will insist that AContainer is also made IDisposable.
Which is fine, but I can't see how I can safely call m_someObject.Dispose() from AContainer.Dispose(), as another class may still have a reference to the m_someObject instance.
What is the best way to avoid this scenario?
(Assume that other code relies on AContainer.SomeObject always having a non-null value, so simply moving the creation of the instance outside of the AContainer is not an option)
Edit: I'll expand with some example as I think some commenters are missing the issue. If I just implement a Dispose() method on AContainer which calls m_someObject.Dispose() then I am left with these situations:
// Example One
AContainer container1 = new AContainer();
SomeDisposableObject obj1 = container1.SomeObject;
container1.Dispose();
obj1.DoSomething(); // BAD because obj1 has been disposed by container1.
// Example Two
AContainer container2 = new AContainer();
SomeObject obj2 = new SomeObject();
container2.SomeObject = obj2; // BAD because the previous value of SomeObject not disposed.
container2.Dispose();
obj2.DoSomething(); // BAD because obj2 has been disposed by container2, which doesn't really "own" it anyway.
Does that help?
There is no single answer, it depends on your scenario, and the key point is ownership of the disposable resource represented by the property, as Jon Skeet points out.
It's sometimes helpful to look at examples from the .NET Framework. Here are three examples that behave differently:
Container always disposes. System.IO.StreamReader exposes a disposable property BaseStream. It is considered to own the underlying stream, and disposing the StreamReader always disposes the underlying stream.
Container never disposes. System.DirectoryServices.DirectoryEntry exposes a Parent property. It is not considered to own its parent, so disposing the DirectoryEntry never disposes its parent.
In this case a new DirectoryEntry instance is returned each time the Parent property is dereferenced, and the caller is presumably expected to dispose it. Arguably this breaks the guidelines for properties, and perhaps there should be a GetParent() method instead.
Container sometimes disposes. System.Data.SqlClient.SqlDataReader exposes a disposable Connection property, but the caller decides if the reader owns (and therefore disposes) the underlying connection using the CommandBehavior argument of SqlCommand.ExecuteReader.
Another interesting example is System.DirectoryServices.DirectorySearcher, which has a read/write disposable property SearchRoot. If this property is set from outside, then the underlying resource is assumed not to be owned, so isn't disposed by the container. If it's not set from outside, a reference is generated internally, and a flag is set to ensure it will be disposed. You can see this with Lutz Reflector.
You need to decide whether or not your container owns the resource, and make sure you document its behavior accurately.
If you do decide you own the resource, and the property is read/write, you need to make sure your setter disposes any reference it's replacing, e.g.:
public SomeDisposableObject SomeObject
{
get { return m_someObject; }
set
{
if ((m_someObject != null) &&
(!object.ReferenceEquals(m_someObject, value))
{
m_someObject.Dispose();
}
m_someObject = value;
}
}
private SomeDisposableObject m_someObject;
UPDATE: GrahamS rightly points out in comments that it's better to test for m_someObject != value in the setter before disposing: I've updated the above example to take account of this (using ReferenceEquals rather than != to be explicit). Although in many real-world scenarios the existence of a setter might imply that the object is not owned by the container, and therefore won't be disposed.
It really depends on who notionally "owns" the disposable object. In some cases, you may want to be able to pass in the object, for instance in the constructor, without your class taking responsibility for cleaning it up. Other times you may want to clean it up yourself. If you're creating the object (as in your sample code) then it should almost certainly be your responsibility to clean it up.
As for the property - I don't think having a property should really transfer ownership or anything like that. If your type is responsible for disposing of the object, it should keep that responsibility.
The real problem might be your object oriented design. If AContainer is Disposed, all its member objects should also be disposed. If not it sound like you can dispose a body but want to keep the leg instance living. Doesn't sound right.
If you have an disposable object on your class you implement IDisposable with a Dispose method that disposes wrapped disposables. Now the calling code has to ensure that using() is used or that an equivalent try / finally code that disposes the object.
I'll try to answer my own question:
Avoid It in the First Place
The easiest way out of this situation is to refactor the code to avoid the problem entirely.
There are two obvious ways to do this.
External instance creation
If AContainer does not create a SomeDisposableObject instance, but instead relies on external code to supply it, then AContainer will no longer "own" the instance and is not responsible for disposing of it.
The externally created instance could be supplied via the constuctor or by setting the property.
public class AContainerClass
{
SomeDisposableObject m_someObject; // No creation here.
public AContainerClass(SomeDisposableObject someObject)
{
m_someObject = someObject;
}
public SomeDisposableObject SomeObject
{
get { return m_someObject; }
set { m_someObject = value; }
}
}
Keep the instance private
The main issue with the posted code is that the ownership is confused. At Dispose time the AContainer class cannot tell who owns the instance. It could be the instance that it created or it could be some other instance that was created externally and set via the property.
Even if it tracks this and knows for certain that it is dealing with the instance that it created, then it still cannot safely dispose of it as other classes may now have a reference to it that they obtained from the public property.
If the code can be refactored to avoid making the instance public (i.e. by removing the property entirely) then the issue goes away.
And If It Can't Be Avoided...
If for some reason the code cannot be refactored in these ways (as I stipulated in the question) then in my opinion you are left with some fairly difficult design choices.
Always Dispose of the instance
If you choose this approach then you are effectively declaring that AContainer will take ownership of the SomeDisposableObject instance when the property is set.
This makes sense in some situations, particularly where SomeDisposableObject is clearly a transient or subservient object. However it should be documented carefully as it requires the calling code to be aware of this transfer of ownership.
(It may be more appropriate to use a method, rather than a property, as the method name can be used to give a further hint about ownership).
public class AContainerClass: IDisposable
{
SomeDisposableObject m_someObject = new SomeDisposableObject();
public SomeDisposableObject SomeObject
{
get { return m_someObject; }
set
{
if (m_someObject != null && m_someObject != value)
m_someObject.Dispose();
m_someObject = value;
}
}
public void Dispose()
{
if (m_someObject != null)
m_someObject.Dispose();
GC.SuppressFinalize(this);
}
}
Only Dispose if still the original instance
In this approach you would track whether the instance was changed from the one originally created by AContainer and only dispose of it when it was the original. Here the ownership model is mixed. AContainer remains the owner of its own SomeDisposableObject instance, but if an external instance is supplied then it remains the responsibility of the external code to dispose of it.
This approach best reflects the actual situation here, but it can be difficult to implement correctly. The client code can still cause issues by performing operations like this:
AContainerClass aContainer = new AContainerClass();
SomeDisposableObject originalInstance = aContainer.SomeObject;
aContainer.SomeObject = new SomeDisposableObject();
aContainer.DoSomething();
aContainer.SomeObject = originalInstance;
Here a new instance was swapped in, a method called, then the original instance was restored. Unfortunately the AContainer will have called Dispose() on the original instance when it was replaced, so it is now invalid.
Just give Up and let the GC handle it
This is obviously less than ideal. If the SomeDisposableObject class really does contain some scarce resource then not disposing of it promptly will definitely cause you issues.
However it may also represent the most robust approach in terms of how the client code interacts with AContainer as it requires no special knowledge of how AContainer treats the ownership of the SomeDisposableObject instance.
If you know that the disposable resource isn't actually scarce on your system then this may actually be the best approach.
Some commenters have suggested that it may be possible to use reference counting to track if any other classes still have a reference to the SomeDisposableObject instance. This would be very useful as it would allow us to dispose of it only when we know it is safe to do so and otherwise just let the GC handle it.
However I am not aware of any C#/.NET API for determining the reference count of an object. If there is one then please let me know.
The reason you cannot safely call Dispose() on AContainer's instance of SomeDisposableObject is due to lack of encapsulation. The public property provides unrestricted access to part of the internal state. As this part of the internal state must obey the rules of the IDisposable protocol, it is important to make sure that is well encapsulated.
The problem is similar to allowing access to an instance used for locking. If you do that, it becomes much harder to determine where locks are acquired.
If you can avoid exposing your disposable instance the problem of who will handle the call to Dispose() goes away as well.
An interesting thing that I've encountered is that SqlCommand owns an SqlConnection (both implement IDisposable) instance usually. However calling dispose on the SqlCommand will NOT dispose the connection too.
I've discovered this also with the help of Stackoverflow right here.
So in other words it matters if the "child" (nested?) instance can/will be reused later.
In general, I think whoever creates the object should be responsible for Disposal. In this case, AContainer creates SomeDisposableObject, so it should be Disposed when AContainer is.
If, for some reason, you think that SomeDisposableObject should live longer than AContainer - I can only think of the following methods:
leave SomeDisposableObject unDisposed, in which case the GC will take care of it for you
give SomeDisposableObject a reference to AContainer (see WinForms Controls and Parent properties). As long as SomeDisposableObject is reachable, so is AContainer. That'll prevent the GC from Disposing AContainer, but if someone calls Dispose manually - well, you'd Dispose SomeDisposableObject. I'd say that's expected.
Implement SomeDisposableObject as a method, say CreateSomeDisposableObject(). That makes it clear(er) that the client is responsible for Disposal.
All in all, though - I'm not really sure the design makes sense. After all, you seem to be expecting client code like:
SomeDisposableObject d;
using (var c = new AContainer()) {
d = c.SomeObject;
}
// do something with d
That seems like broken client code to me. It's violating Law of Demeter, and plain ol' common sense to me.
Design you have mentioned here is not something could handle this scenario. You said there is a container for that class then it should dispose it along with itself. If other objects may be using it then it is not the container and scope of you class widens and it need to dispose at boundary of that scope.
You could just flag the Disposal in Dispose(). After all Disposal isn't a destructor - the object still exists.
so:
class AContainer : IDisposable
{
bool _isDisposed=false;
public void Dispose()
{
if (!_isDisposed)
{
// dispose
}
_isDisposed=true;
}
}
add this to your other class, too.

Categories

Resources