4

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

}
Adel Khayata
  • 2,717
  • 10
  • 28
  • 46
  • 3
    If you read about setting `this` to `null` somewhere, please tell us where you read it. We should avoid whatever your source is. – John Saunders Jul 27 '13 at 17:58
  • possible duplicate of [Proper use of the IDisposable interface](http://stackoverflow.com/questions/538060/proper-use-of-the-idisposable-interface) – Erik Philips Jul 27 '13 at 17:59
  • You cannot set an _object_ to null. Only references to it, with the exception of `this`. The most common case for cleaning up is: do nothing. – H H Jul 27 '13 at 18:10
  • You can assign to `this` only inside a `struct`, not inside a `class`. But normally `null` cannot be converted to the `struct` type, so you still can't assign `null`. But anyway that is not the way to dispose of special ressources held by the class or struct. If no special ressources are actually held, don't implement `IDisposable` in the first place. – Jeppe Stig Nielsen Jul 27 '13 at 18:36
  • @JeppeStigNielsen `You can assign to this only inside a struct`. Holy cow, you **can** do that. Why though? – sircodesalot Sep 25 '13 at 18:49
  • @sircodesalot It is not very often something you do, because mutable structs are considered "evil". But just ***try it***. Write a struct, write a non-static constructor or method inside it. And write `this = x;` where `x` is another value of your struct (`x` might be a parameter). You can regard `this` as a kind of `ref` parameter (or even an `out` parameter in case of the instance constructor of a struct). – Jeppe Stig Nielsen Sep 25 '13 at 19:10
  • @JeppeStigNielsen Oh I did, that's how I know it works. I just cannot for the life of me understand what practical application there is. – sircodesalot Sep 25 '13 at 19:18
  • @sircodesalot I don't know. Maybe something like `struct Triple { public int X; public int Y; public int Z; public Triple(int x, int y, int z) { Triple t; t.X = x; t.Y = y; t.Z = z; this = t; } public void Rotate() { this = new Triple(Y, Z, X); } }` shows how you *could* code if you really wanted a mutable value-type. Of course the instance constructor is a little silly because you could just as well assign `X`, `Y` and `Z` of `this` directly, as you usually do in instance constructors. But note how `t` can be assigned in a "step-wise" manner. But inside the method, maybe I found a good use? – Jeppe Stig Nielsen Sep 25 '13 at 19:40

6 Answers6

9

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.

Daniel Mann
  • 57,011
  • 13
  • 100
  • 120
5

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

sircodesalot
  • 11,231
  • 8
  • 50
  • 83
  • As far as i know the using pattern is a safeguard (handy!) to make sure IDisposable is called within the given scope. The class that implements it will check if a connection is closed, and calling Close for you if you didn't. using is equivalent to a try/finally block. To make sure Close() is called. If you do not use dispose or a using, you still have to write a ~finalzer to call the dispose.. – Rob van der Veer Jul 27 '13 at 18:03
  • @RobvanderVeer Additionally: Dispose() is better for performance than letting the GC call upon the Finalize() function. – Recipe Jul 27 '13 at 18:09
  • @Recipe, There is no deterministic finalize in C#, and that is the reason of implementing `IDisposable`. – Rob van der Veer Jul 27 '13 at 18:54
  • Note to people considering using a finalizer: If you write a finalizer in .NET, and you are not an expert in finalization in .NET (which is very different from destructors in C++), then you probably did something wrong. This includes using code copy/pasted from the internet (e.g. many examples for `IDisposable` include a finalizer when in fact they should not). – Sam Harwell Jul 27 '13 at 23:49
1

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.

Moti Azu
  • 5,392
  • 1
  • 23
  • 32
1

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)

Community
  • 1
  • 1
Aaron Viviano
  • 306
  • 2
  • 6
0

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)

Rowland Shaw
  • 37,700
  • 14
  • 97
  • 166
  • Then how do I set this object to null? it must be outside MyClass? – Jorge Tovar Jul 27 '13 at 17:57
  • @JorgeTovar There's no need to set the object to `null`. – Daniel Mann Jul 27 '13 at 17:57
  • You might want to read up on garbage collection - the short version is that you should only implement IDisposable if you have members that are IDispobable, or you reference native resources that require release. – Rowland Shaw Jul 27 '13 at 18:01
  • @JorgeTovar The object will be set to null when it goes out of scope or when the owner of the object sets it to null. Remember that this means that the object itself has no reference to the instance anymore. If that instance has no other references linked, it will get picked up by the garbage collector. – Recipe Jul 27 '13 at 18:02
0

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)

Rob van der Veer
  • 1,148
  • 1
  • 7
  • 20
  • 1
    It's also a good idea to implement `IDisposable` if you're holding on to *other* classes that implement `IDisposable`. For example, if you stick a stream in a private field in your class, your class should implement `IDisposable` so that it can call `Dispose()` on the stream. – Daniel Mann Jul 27 '13 at 18:16