-1

I have inherited a C# class. This class has two properties which are IDisposable. However, the class itself does not IDisposable. For the context of this conversation, let's pretend the class looks like this:

public class MyParentClass
{
  public List<string>.Enumerator List = new List<string>.Enumerator();

  public MyParentClass()
  {
  }
} 

Now, let's pretend I have a method in my class called ExecuteWork:

public void ExecuteWork()
{
  var pc = new MyParentClass();
  Console.WriteLine("All done!");
}

Would List ever get disposed? Or, would it just hang around in memory?

Developer
  • 89
  • 1
  • 4
  • It holds the enumerator? Not the list? I wouldn't call an enumerator `List`. Anyhow, all disposing is manual anyhow. If you don't trigger it, either manual or with a `using` block, it's nerve triggered. Can't you add a IDisposable inheritance? – JHBonarius May 19 '23 at 18:40

3 Answers3

0

That member of MyParentClass which you call List is not a list; it is an enumerator. Please name your variables properly.

Yes, this enumerator will not be disposed.

This does not mean that it will stay in memory forever; it just means that its finalizer will never be invoked. So, if that enumerator is controlling some unmanaged resource, then that unmanaged resource will never be cleaned up. But do not worry about the memory, it will be taken care of.

Also note: it is a grave mistake to put a disposable member inside a non-disposable class. If a class has disposable members, then the class itself must be disposable, so that it can dispose of those members. So, you have a faulty design in your hands.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
0

List will not get disposed but it will get destroyed by the garbage collector when there are no more references to it, which in this case means that there are no more references to the containing object.

However, you don't control when that happens. If there is no memory pressure, it might remain in memory as long as the process is alive.

Using IDisposable just lets you control when the object is disposed, which is more important for unmamaged resources that need to be released in a timely manner. For an Enumerator on a list (which is an odd thing to hold a reference to anyways), it may not be critical to explicitly dispose of it.

Best practices, however, say that if a class contains an IDisposable reference, then it should implement IDisposable as well and dispose of the references it its Dispose method.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
0

You should release allocated resouces (IDisposable instances). In your case it is MyParentClass who allocates, that's why it should Dispose it:

public class MyParentClass {
  // Let it be a property - user is not supposed to assign value here
  public List<string>.Enumerator MyEnumerator {get; private set;} = 
    new List<string>.Enumerator();

  // Here we dispose allocated resources
  protected virtual void Dispose(bool disposing) {
    if (disposing) {
      if (MyEnumerator is not null)
        MyEnumerator.Dispose();

      MyEnumerator = null;   
    }
  }

  // IDisposable interface implementation  
  public Dispose() => Dispose(true);
}  

When you implement derived class you don't have to do anything, since MyParentClass provides all required code:

public class MyDerivedClass : MyParentClass {
}

If MyNextDerivedClass has anything to dispose, just override Dispose and add required code:

public class MyNextDerivedClass : MyParentClass {
  public List<string>.Enumerator MyOtherEnumerator {get; private set;} = 
    new List<string>.Enumerator();

  protected override void Dispose(bool disposing) {
    // dispose MyParentClass resource
    base.Dispose(bool);

    // extra code to dispose MyNextDerivedClass own resources 
    if (disposing) {
      if (MyOtherEnumerator is not null)
        MyOtherEnumerator.Dispose();

      MyOtherEnumerator = null; 
    }
  }
}
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215