Jorge Tovar
Jorge Tovar

Reputation: 67

Simple destructor issue (IDisposable interface)

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;
    }

}

Upvotes: 4

Views: 307

Answers (6)

sircodesalot
sircodesalot

Reputation: 11439

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).

Upvotes: 5

Aaron Viviano
Aaron Viviano

Reputation: 306

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)

Upvotes: 1

Rob van der Veer
Rob van der Veer

Reputation: 1148

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)

Upvotes: 0

Moti Azu
Moti Azu

Reputation: 5442

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.

Upvotes: 1

Daniel Mann
Daniel Mann

Reputation: 58981

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.

Upvotes: 9

Rowland Shaw
Rowland Shaw

Reputation: 38130

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)

Upvotes: 0

Related Questions