开发者

Will Dispose() cause a release of resources ahead of time in this case?

开发者 https://www.devze.com 2023-01-08 04:45 出处:网络
I ha开发者_Python百科ve this class: class Foo : IDisposable { SomeBigResource resource; void UsingResource()

I ha开发者_Python百科ve this class:

class Foo : IDisposable
{
  SomeBigResource resource;

  void UsingResource()
  {
    using(Bar bar = new Bar(SomeBigResource)
      bar.doStuff();
  }

  void Dispose()
  {
    resource.Dispose();
  }
}

void Function()
{
  using (Foo foo = new Foo(new SomeBigResource))
    foo.UsingResource();
}

The Bar object has exactly the same Dispose() function.

Will my SomeBigResource be released or is the GC smart enough to release it later on when the second using is done?


If both the Dispose methods in Foo and Bar calls Dispose on the SomeBigResource object, the method will be called twice. If the method is implemented correctly it will release the resources the first time and do nothing the second time.

What you have is a confusion of responsibility, where both objects take responsibility for calling Dispose on the SomeBigResource object. This is something that you want to avoid, as one object can't know if the other object still needs the resource, so you want to put the responsibility in one place only.

You should either make the Foo object responsible for the life cycle of the resource, or handle it outside of the objects completely. The latter makes more sense, as that's where you create the SomeBigResource instance:

using (SomeBigResource resource = new SomeBigResource()) {
  using (Foo foo = new Foo(resource)) {
    foo.UsingResource();
  }
}


Your resource will be disposed twice.

The GC is completely unaware of IDisposables and the using statement.

Each using statement translates into a try / finally block with a Dispose() call in the finally block.
This is a normal method call which will always execute.

Therefore, the inner using statement in UsingResource() will dispose the resource, and then the outer using statement in Function() will dispose it again.

All IDisposable implementations should be idempotent (calling it a second time should do no harm). Therefore, (assuming that SomeBigResource implements IDisposable correctly), your code should work fine.

Note, though, that with your class, an empty using block will throw a NullReferenceException, which is very wrong.
You should add a null check in your Dispose method.


This depends on the implementation of Bar.Dispose(). Assuming it has a similar implementation as Foo, then, yes, the release will occur early.

Take a look at the Dispose pattern guidance and this SO question. There are more corner cases than you may think of immediately.


I assume this line should read:

using(Bar bar = new Bar(resource))

If that's the case, then when bar is disposed, it should dispose of resource.

So, yes. When bar is disposed in UsingResource, it will dispose resource, so that if you attempt to use it later, it should throw an ObjectDisposedException. (Although in your simple example, that shouldn't happen.)

0

精彩评论

暂无评论...
验证码 换一张
取 消