2

NET for a long time now and have started to learn C#. One thing I suppose I may have asked years ago, got the answer but have completely forgotten it now as it is not something I implicitly use a lot is destructors. As I am going through learning C# I read an article about how to create these in C# however it has left me wondering. Let say I instantiate a class which has an object to another class.

Class C1
{
  // Do something here
}

Class A
{
  C1 objObjectToClass1 = new C1();
}   

Class Main
{
   A objObjectToClassA = new A();
}

and I make the object objObjectToClassA to null as I have been lead to believe that is the equivalent to object = nothing in VB.NET.

objObectToClassA = null;

Does this action also destroy objObjectToClass1?

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
altaaf.hussein
  • 274
  • 2
  • 13

4 Answers4

5

Not as such, no. An object will be reclaimed by the garbage collector some time after it has become eligible for collection. This may be after you clear the last reference to it, but it could already be before if you never need the reference anymore after a certain point. But generally, setting a field where you store the instance to null will help the object becoming no longer reachable and getting reclaimed.

Generally you have no control over when objects are reclaimed by the GC. You can write finalizers which are methods that are called prior to reclaiming an object, but I'd very much not recommend it if you can help it. If you need a predictable way of causing an object to release any resources it might hold on to (what destructors in C++ often do), then implement the IDisposable interface:

class C1 : IDisposable {
  public void Dispose() {
    // Do cleanup here
  }
}

This also enables you to use instances of that class in a using statement, which will call Dispose at the end of its block:

using (var c1 = new C1()) {
  // do stuf with c1 here
} // at this point c1.Dispose() is automatically called
Joey
  • 344,408
  • 85
  • 689
  • 683
  • so does that mean setting it to null will remove any reference and that will be cascaded down to all objects within the object i set to null. Sorry my mistake should have worded ti better I know it will still be there until GC comes to collect it but this was one of the ways I used VB.NET to explicitly tell the GC that I am no longer using this object – altaaf.hussein Aug 12 '16 at 09:59
  • "Generally you have no control..." - Well technically there is [GC.Collect()](https://msdn.microsoft.com/de-de/library/system.gc.collect%28v=vs.110%29.aspx). But since you said generally, i suppose you are right. – Toastgeraet Aug 12 '16 at 09:59
  • @altaaf.hussein: Setting a field to `null` will remove *one* reference. If that was the only one left, then yes, the object should be eligible for collection. But there are lots of ways in which you can leak instances, e.g. via event handlers, closures, etc. that are not immediately obvious. So no, *in general*, setting something to `null` will not guarantee the GC to collect a certain object instance. – Joey Aug 12 '16 at 10:01
  • 1
    @Toastgeraet: That's a method most .NET developers should never touch ;-) – Joey Aug 12 '16 at 10:02
  • Mr Skeet is giving a nice example of when using GC.Collect might be fine in his [answer to another question](http://stackoverflow.com/a/478177/2503977). – Toastgeraet Aug 12 '16 at 10:14
2

The garbage collector knows when there are no references any more to objects, and as far as I know, it even destroys objects that are only referenced by another.

That means that if you dereference objObjectToClassA (set it to null), that both objects will get destroyed, if there are no more references to either of the objects. Simply letting it go out of scope is enough too.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
1

In effect, yes it will also destroy objectToClass1, but not immediately. In this case, setting the variable to null means that your application is no longer using that object, and hence it's eligible for garbage collection. Thinking about it simplistically (I'm sure the GC is smarter than this), once objectToClassA is collected then objectToClass1 is no longer referenced and will also be collected.

Joey's comments about IDisposable are definitely worth bearing in mind; try not to think in terms of finalisers for C# as you don't have control over when they run. Using IDisposable will give you the control that you need in order to tidy up resources.

Ade Stringer
  • 2,611
  • 17
  • 28
  • Except .NET objects are not reference-counted; objects are eligible for collection when there is no reference path to a root, not when they are no longer referenced. – Joey Aug 12 '16 at 12:42
  • Fair comment; I've removed the mentions of reference counting. I don't really think that the precise way the garbage collector works is important here; the key is that the garbage collector decides when to clean up, and hence you can't control when finalisers will run... – Ade Stringer Aug 12 '16 at 13:22
0

Destroy is the wrong word, C# (as far as I know) does not have destructors in the C++ sense. No longer used objects are collected/"destroyed" by the garbage collector.

If no other reference to objObjectToClass1 is kept, objObjectToClass1 can also be collected if you set objObectToClassA to null

Chandan Kumar
  • 4,570
  • 4
  • 42
  • 62
ArgusMagnus
  • 679
  • 5
  • 14
  • 1
    Not in c++ sense, but it does have a destructor in form of finalizer, which aids the sure shot object collection by GC, which is otherwise undeterministic or we can even use Dispose to completely suppress the finalization – Mrinal Kamboj Aug 12 '16 at 09:58
  • That's why I wrote not in the C++ sense. Finalizers offer some similar functionality but are very different to C++ destructors. And Finalizers are not deterministic either. – ArgusMagnus Aug 12 '16 at 10:00
  • That's not apple to apple comparison, because there's no GC in C++ for memory management, so not a fair comparison. Comparison with Java would be far more relevant. Btw I didn't downvote. – Mrinal Kamboj Aug 12 '16 at 10:02
  • Since the OP used the word "destructor" it seemed likely that he came from C/C++ and it seemed worth it to point out the difference. Why would I want to compare it to Java? – ArgusMagnus Aug 12 '16 at 10:05