C# disposable objects - c#

Are there some advices about how I should deal with the IDisposable object sequences?
For example, I have a method that builds a IEnumerable<System.Drawing.Image> sequence and
at some point I would need to dispose that objects manually, because otherwise this might lead to some leaks.
Now, is there a way to bind the Dispose() call to garbage collector actions, because I want these objects disposed right in the moment they are no longer accessible from other code parts?
**Or maybe you could advice me some other approach? **
Generally, this seems to be the same problem as it comes, for example, in unmanaged C++ without shared pointers, where you can have a method:
SomeObject* AllocateAndConstruct();
and then you can't be sure when to dispose it, if you don't use code contracts or don't state something in the comments.
I guess the situation with disposable objects is pretty the same, but I hope there is an appropriate solution for this.

(from the question)
Now, is there a way to bind the
Dispose() call to garbage collector
actions, because I want these objects
disposed right in the moment they are
no longer accessible from other code
parts?
GC doesn't happen immediately when your object goes out of scope / reach; it is non-deterministic. By the time GC sees it, there is no point doing anything else (that isn't already handled by the finalizer), as it is too late.
The trick, then, is to know when you are done with it, and call Dispose() yourself. In many cases using achieves this. For example you could write a class that implements IDisposable and encapsulates a set of Images - and wrap your use of that encapsulating object with using. The Dispose() on the wrapper could Dispose() all the images held.
i.e.
using(var imageWrapper = GetImages()) {
foreach(var image in imageWrapper) {
...
}
// etc
} // assume imageWrapper is something you write, which disposes the child items
however, this is a bit trickier if you are displaying the data on the UI. There is no shortcut there; you will have to track when you are done with each image, or accept non-deterministic finalization.

If you want to determiniscally dispose of the objects in the collection, you should call Dispose on each:
myImages.ToList().ForEach(image => image.Dispose());
If you don't do this, and if your objects become unreachable, the GC will eventually run and release them.
Now, if you don't want to manually code the Dispose calls, you can create a wrapper class that implements IDisposable and use it through a using statement:
using (myImages.AsDisposable()) {
// ... process the images
}
This is the needed "infrastructure":
public class DisposableCollectionWrapper<D> : IDisposable
where D : IDisposable {
private readonly IEnumerable<D> _disposables;
public DisposableCollectionWrapper(IEnumerable<D> disposables) {
_disposables = disposables;
}
public void Dispose() {
if (_disposables == null) return;
foreach (var disposable in _disposables) {
disposable.Dispose();
}
}
}
public static class CollectionExtensions {
public static IDisposable AsDisposable<D>(this IEnumerable<D> self)
where D : IDisposable {
return new DisposableCollectionWrapper<D>(self);
}
}
Also notice that this is not the same as the situation you described with C++. In C++, if you don't delete your object, you have a genuine memory leak. In C#, if you don't dispose of your object, the garbage collector will eventually run and clean it up.

You should design your system in a way that you know when the resources are no longer needed. In the worst case, they'll be eventually disposed when the garbage collector gets to it, but the point of IDisposable is that you can release important resources earlier.
This "earlier" is up to you to define, for example, you can release them when the window that's using them closes, or when your unit of work finishes doing whatever operations on them. But at some point, some object should "own" these resources, and therefore should know when they're no longer needed.

You can use the 'using' block, to make sure, the IDisposable is disposed as soon the block is left. The compiler does encapsulate such blocks into try - finally statements in order to make sure, Dispose is called in any case when leaving the block.
By using a finalizer, one can make the GC call the Dispose method for those objects which where "missed" somehow. However, implementing a finalizer is more expensive and decreases the garbage collection efficiency - and possibly the overall performance of your application. So if any possible, you should try to make sure to dispose your IDisposables on your own; deterministically:
public class Context : IDisposable {
List<IDisposable> m_disposable = new List<IDisposable>();
public void AddDisposable(IDisposable disposable) {
m_disposable.Add(disposable);
}
public void Dispose() {
foreach (IDisposable disp in m_disposable)
disp.Dispose();
}
// the Context class is used that way:
static void Main(string[] args) {
using (Context context = new Context()) {
// create your images here, add each to the context
context.AddDisposable(image);
// add more objects here
} // <- leaving the scope will dispose the context
}
}
By using some clever design, the process of adding objects to the context may can get even more easier. One might give the context to the creation method or publish it via a static singleton. That way, it would be available for child method scopes as well - without having to pass a reference to the contex around. By utilizing that scheme it is even possible, to simulate an artificial destructor functionality like f.e. known from C++.

The neat method would be to create your own generic collection class that implements IDisposable. When this collection class is Disposed() ask for each element if it implements IDisposed, and if so Dispose it.
Example (look elsewhere if you don't know about the IDisposable pattern)
public class MyDisposableList<T> : List<T> : IDisposable
{
private bool disposed = false;
~MyDisposableList()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected void Dispose(bool disposing)
{
if (!disposed)
{
foreach (T myT in this)
{
IDisposable myDisposableT = myT as IDisposable;
if (myDisposableT != null)
{
myDisposableT.Dispose();
}
myT = null;
}
this.Clear();
this.TrimExcess();
disposed = true;
}
}
...
}
usage:
using (MyDisposableList<System.Drawing.Bitmap> myList = new ...)
{
// add bitmaps to the list (bitmaps are IDisposable)
// use the elements in the list
}
The end of the using statement automatically Disposes myList, and thus all bitMaps in myList
By the way: if you loaded the bitmap from a file and you forgot to Dispose() the bitmap you don't know when you can delete that file.

You can call GC.Collect() if you really was to dispose those objects right away but to my understanding it is up to the GC to decide whether to collect the memory.
This in turn will call the Finalize() method for each object that should be released.
Note that if the collection goes out of scope the GC will eventually collect the memory used by the images.
You can also use the using construct if you use a collection that implements IDisposeable. That will guarantee that the objects will be disposed exactly when the collection goes out of scope (or nearly after the end of the scope).

Related

Should I Treat Entity Framework as an Unmanaged Resource?

I am working with a class that uses a reference to EF in its constructor.
I have implemented IDisposable, but I'm not sure if I need a destructor because I'm not certain I can classify EF as an unmanaged resource.
If EF is a managed resource, then I don't need a destructor, so I think this is a proper example:
public ExampleClass : IDisposable
{
public ExampleClass(string connectionStringName, ILogger log)
{
//...
Db = new Entities(connectionStringName);
}
private bool _isDisposed;
public void Dispose()
{
if (_isDisposed) return;
Db.Dispose();
_isDisposed= true;
}
}
If EF is unmanaged, then I'll go with this:
public ExampleClass : IDisposable
{
public ExampleClass(string connectionStringName, ILogger log)
{
//...
Db = new Entities(connectionStringName);
}
public void Dispose()
{
Dispose(true);
}
~ExampleClass()
{
Dispose(false);
}
private bool _isDisposed;
protected virtual void Dispose(bool disposing)
{
if (_isDisposed) return;
// Dispose of managed resources
if (disposing)
{
// Dispose of managed resources; assumption here that EF is unmanaged.
}
// Dispose of unmanaged resources
Db.Dispose();
_isDisposed = true;
//freed, so no destructor necessary.
GC.SuppressFinalize(this);
}
}
Which one is it?
You would never want to use a finalizer (destructor) in this case.
Whether DbContext contains unmanaged resources or not, and even whether it responsibly frees those unmanaged resources or not, is not relevant to whether you can try to invoke DbContext.Dispose() from a finalizer.
The fact is that, any time you have a managed object (which an instance of DbContext is), it is never safe to attempt to invoke any method on that instance. The reason is that, by the time the finalizer is invoked, the DbContext object may have already been GC-collected and no longer exist. If that were to happen, you would get a NullReferenceException when attempting to call Db.Dispose(). Or, if you're lucky, and Db is still "alive", the exception can also be thrown from within the DbContext.Dispose() method if it has dependencies on other objects that have since been finalized and collected.
As this "Dispose Pattern" MSDN article says:
X DO NOT access any finalizable objects in the finalizer code path, because there is significant risk that they will have already been finalized.
For example, a finalizable object A that has a reference to another finalizable object B cannot reliably use B in A’s finalizer, or vice versa. Finalizers are called in a random order (short of a weak ordering guarantee for critical finalization).
Also, note the following from Eric Lippert's When everything you know is wrong, part two:
Myth: Finalizers run in a predictable order
Suppose we have a tree of objects, all finalizable, and all on the finalizer queue. There is no requirement whatsoever that the tree be finalized from the root to the leaves, from the leaves to the root, or any other order.
Myth: An object being finalized can safely access another object.
This myth follows directly from the previous. If you have a tree of objects and you are finalizing the root, then the children are still alive — because the root is alive, because it is on the finalization queue, and so the children have a living reference — but the children may have already been finalized, and are in no particularly good state to have their methods or data accessed.
Something else to consider: what are you trying to dispose? Is your concern making sure that database connections are closed in a timely fashion? If so, then you'll be interested in what the EF documentation has to say about this:
By default, the context manages connections to the database. The context opens and closes connections as needed. For example, the context opens a connection to execute a query, and then closes the connection when all the result sets have been processed.
What this means is that, by default, connections don't need DbContext.Dispose() to be called to be closed in a timely fashion. They are opened and closed (from a connection pool) as queries are executed. So, though it's still a very good idea to make sure you always call DbContext.Dispose() explicitly, it's useful to know that, if you don't do it or forget for some reason, by default, this is not causing some kind of connection leak.
And finally, one last thing you may want to keep in mind, is that with the code you posted that doesn't have the finalizer, because you instantiate the DbContext inside the constructor of another class, it is actually possible that the DbContext.Dispose() method won't always get called. It's good to be aware of this special case so you are not caught with your pants down.
For instance, suppose I adjust your code ever so slightly to allow for an exception to be thrown after the line in the constructor that instantiates the DbContext:
public ExampleClass : IDisposable
{
public ExampleClass(string connectionStringName, ILogger log)
{
//...
Db = new Entities(connectionStringName);
// let's pretend I have some code that can throw an exception here.
throw new Exception("something went wrong AFTER constructing Db");
}
private bool _isDisposed;
public void Dispose()
{
if (_isDisposed) return;
Db.Dispose();
_isDisposed= true;
}
}
And let's say your class is used like this:
using (var example = new ExampleClass("connString", log))
{
// ...
}
Even though this appears to be a perfectly safe and clean design, because an exception is thrown inside the constructor of ExampleClass after a new instance of DbContext has already been created, ExampleClass.Dispose() is never invoked, and by extension, DbContext.Dispose() is never invoked either on the newly created instance.
You can read more about this unfortunate situation here.
To ensure that the DbContext's Dispose() method is always invoked, no matter what happens inside the ExampleClass constructor, you would have to modify the ExampleClass class to something like this:
public ExampleClass : IDisposable
{
public ExampleClass(string connectionStringName, ILogger log)
{
bool ok = false;
try
{
//...
Db = new Entities(connectionStringName);
// let's pretend I have some code that can throw an exception here.
throw new Exception("something went wrong AFTER constructing Db");
ok = true;
}
finally
{
if (!ok)
{
if (Db != null)
{
Db.Dispose();
}
}
}
}
private bool _isDisposed;
public void Dispose()
{
if (_isDisposed) return;
Db.Dispose();
_isDisposed= true;
}
}
But the above is really only a concern if the constructor is doing more than just creating an instance of a DbContext.
C# provides garbage collection and thus does not need an explicit destructor. If you do control an unmanaged resource, however, you will need to explicitly free that resource when you are done with it. Implicit control over this resource is provided with a Finalize( ) method (called a finalizer), which will be called by the garbage collector when your object is destroyed.
https://www.oreilly.com/library/view/programming-c/0596001177/ch04s04.html

using statement usage in C#

I have some doubts regarding the using statement:
I have a class called
MyJob which is Disposable. Then i also have a property on MyJob JobResults that is also Disposable.
MY code:
using (MyJob job = new MyJob())
{
//do something.
FormatResults(job.JobResults)
}
public string FormatResuls(JobResuts results)
{
}
MY First question is: In this case after the using block are both MyJob and MyJob.Results disposed or only MyJob and NOT MyJob.Results?
I am also performing parallel processing w.r.t Tasks in C#:
Tasks allTasks = List<Tasks>
try
{
foreach(Task t in allTasks)
{
// Each tasks makes use of an IDisposable object.
t.Start();
}
Task.WaitAll(allTasks);
}
catch(AggregateExecption aex)
{
/// How do I ensure that all IDisposables are disposed properly if an exception happens in any of the tasks?
}
My second q, in the code above, what is the proper way to ensure to dispose off objects correctly when handling exceptions in tasks?
Sorry if my questions are too naive or confusing, as i am still trying to learn and understand C#.
Thanks guys!
are both MyJob and MyJob.Results disposed or only MyJob and NOT
MyJob.Results?
That is subjective to the implementation of your Dispose method. As we haven't seen it in your question, I'll assume that you aren't currently disposing your Result property in MyJob.Dispose, hence it will be the latter.
As only MyJob is wrapped in a using statement, and again assuming it does nothing to your Result property, it will be disposed as opposed to Results, which isn't wrapped in a using statement.
You could decide that MyJob, as it encapsulates your Result property, is responsible for the disposable of it as well. If you decide so, you can dispose Results in MyJobs.Dispose.
what is the proper way to ensure to dispose off objects correctly when
handling exceptions in tasks?
If the delegate which is passed to the Task is wrapped in a using statement, you are safe, since using will transform your code to a try-finally block, if an exception occurs in your using block, the finally block will still run yourObject.Dispose.
Only MyJobs is disposed. For other properties, you need to understand object ownership: who owns the object should be responsible (in general) to dispose of it. A property implementing IDisposable could be used by other instances, so you can only dispose of it if you are the one who created it and there no other references to it, or the class fails gracefully if it knows that it has been disposed of.
There are a lot of good answers here but one thing remains. If you want to be assured that your object is properly disposed because it uses unmanaged resources, you should implement a destructor in your object, like:
class MyJob : IDisposable
{
private bool _disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
//Dispose unmanaged resources and any child disposables here
}
}
void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
~MyJob()
{
//ONLY use if you have unmanaged resources that DO NOT
//implement their own finalizers.
Dispose();
}
}
However, it is recommended that you DO NOT use a finalizer (destructor) unless you are finalizing a type with unmanaged resources that does not include its own finalizer.
See https://msdn.microsoft.com/en-us/library/b1yfkh5e.aspx for best practices on implementing IDisposable.
1) The best way is to dispose JobResults inside of MyJob's Dispose() methode. Otherwise it's not disposed on it's own
2) I would implement the finally part, go through every object and dispose it. But in most cases you donät need to do that read this

Do this dispose the child objects or not?

I have two classes, say class MyFirstClass and MyAnotherClass , MyAnotherClass is implementing IDiposable interface.
public class MyFirstClass
{
public string xyz{get;set;} ..... and so on
}
public class MyAnotherClass : IDisposable
{
private readonly MyFirstClass objFc = new MyFirstClass();
public static void MyStaticMethod()
{
var objOfFirstClass = new MyFirstClass();
// something with above object
}
public void MyNonStaticMethod()
{
// do something with objFc
}
#region Implementation of IDisposable
.... my implementations
#endregion
}
Now I have one more class where I am calling MyAnotherClass , something like this
using(var anotherObj = new MyAnotherClass())
{
// call both static and non static methods here, just for sake of example.
// some pretty cool stuffs goes here... :)
}
So I would like to know, should I worry about the cleanup scenario of my objects? Also, what will happen to my ObjFC (inside non static) and the objOfFirstClass (inside static).
AFAIK, using will take care of everything...but i need to know more...
objOfFirstClass is a local variable in a method. It will be eligible for garbage collection once the method is exited. It won't be disposed as such because it doesn't implement IDisposable.
objFc will be eligible for garbage collection when its parent object goes out of scope. Again, this is nothing to do with disposing it.
Dispose/IDisposable is used when there is clean up other than simple memory management to be done. The CLR handles cleaning up the memory for you using garbage collection. using is a nice way of ensuring that an object implementing IDisposable has its Dispose method called when you have finished with it - but if all you are after is memory management, you don't need to use it.
IDisposable indicates that an object is using resources other than managed memory; for example, file handles. The Dispose method is supposed to handle the clean-up of these resources (and that's what your implementation should do).
Any CLR-native object (e.g. those in your example) is garbage collected by the CLR when no more references to it exist (more specifically, by a mechanism called the garbage collector or GC); IDisposable is unnecessary in these cases.
In order to make use of IDisposable you have to call Dispose yourself (or use using, which is just syntactic sugar). It isn't called automatically by the GC.
There is not any magic behind IDisposable except that using calls the Dispose method.
As the class MyFirstClass does not implement IDisposable, there is no need to worry about instances of this class - they should not have anything to dispose.
If you have fields or variables that need to be disposed, you have to call Dispose. Additionally, you should implement a destructor that calls the Dispose method, as the reference proposes:
~MyClass() {
Dispose(false);
}
Where the boolean parameter specifies that fields should not be disposed, in this case. For details, see the linked msdn page.
IDispose disposes the class MyAnotherClass. This means that local variables of the MyFirstClass object are pointing to nothing. Therefore, they are reclaimed once the garbage collector runs.

IDisposable Question

Say I have the following:
public abstract class ControlLimitBase : IDisposable
{
}
public abstract class UpperAlarmLimit : ControlLimitBase
{
}
public class CdsUpperAlarmLimit : UpperAlarmLimit
{
}
Two Questions:
1.
I'm a little confused on when my IDisposable members would actually get called. Would they get called when an instance of CdsUpperAlarmLimit goes out of scope?
2.
How would I handle disposing of objects created in the CdsUpperAlarmLimit class? Should this also derive from IDisposable?
Dispose() is never called automatically - it depends on how the code is actually used.
1.) Dispose() is called when you specifically call Dispose():
myAlarm.Dispose();
2.) Dispose() is called at the end of a using block using an instance of your type.
using(var myAlarm = new CdsUpperAlarmLimit())
{
}
The using block is syntactic sugar for a try/finally block with a call to Dispose() on the object "being used" in the finally block.
No, IDisposable won't be called just automatically. You'd normally call Dispose with a using statement, like this:
using (ControlLimitBase limit = new UpperAlarmLimit())
{
// Code using the limit
}
This is effectively a try/finally block, so Dispose will be called however you leave the block.
CdsUpperAlarmLimit already implements IDisposable indirectly. If you follow the normal pattern for implementing IDisposable in non-sealed classes, you'll override void Dispose(bool disposing) and dispose your composed resources there.
Note that the garbage collector does not call Dispose itself - although it can call a finalizer. You should rarely use a finalizer unless you have a direct handle on unmanaged resources though.
To be honest, I usually find it's worth trying to change the design to avoid needing to keep hold of unmanaged resources in classes - implementing IDisposable properly in the general case is frankly a pain. It's not so bad if your class is sealed (no need for the extra method; just implement the Dispose() method) - but it still means your clients need to be aware of it, so that they can use an appropriate using statement.
IDisposable has one member, Dispose().
This is called when you choose to call it. Most typically that's done for you by the framework with the using block syntactic sugar.
I'm a little confused on when my IDisposable members would actually get called. Would they get called when an instance of CdsUpperAlarmLimit goes out of scope?
No. Its get called when you use using construct as:
using(var inst = new CdsUpperAlarmLimit())
{
//...
}//<-------- here inst.Dispose() gets called.
But it doesn't get called if you write this:
{
var inst = new CdsUpperAlarmLimit();
//...
}//<-------- here inst.Dispose() does NOT get called.
However, you can write this as well:
var inst = new CdsUpperAlarmLimit();
using( inst )
{
//...
}//<-------- here inst.Dispose() gets called.
The best practice recommend when you implement Dispose() method in non sealed class you should have a virtual method for your derived classes to override.
Read more on Dispose pattern here http://www.codeproject.com/KB/cs/idisposable.aspx
when using an IDisposable object, it's always good to use it this way:
using(var disposable = new DisposableObject())
{
// do you stuff with disposable
}
After the using block has been run, the Dispose method will be called on the IDisposable object. Otherwise you would need to call Dispose manually.
When someone calls .Dispose on it.
No, it already implements it through inheritance.
IDisposable is implemented when you want to indicate that your resource has dependencies that must be explicitly unloaded and cleaned up. As such, IDisposable is never called automatically (like with Garbage Collection).
Generally, to handle IDisposables, you should wrap their usage in a using block
using(var x = new CdsUpperAlarmLimit()) { ... }
this compiles to:
CdsUpperAlarmLimit x = null;
try
{
x = new CdsUpperAlarmLimit();
...
}
finally
{
x.Dispose();
}
So, back to topic, if your type, CdsUpperAlarmLimit, is implementing IDisposable, it's saying to the world: "I have stuff that must be disposed". Common reasons for this would be:
CdsUpperAlarmLimit keeps some OTHER IDisposable resources (like FileStreams, ObjectContexts, Timers, etc.) and when CdsUpperAlarmLimit is done being used, it needs to make sure the FileStreams, ObjectContexts, Timers, etc. also get Dispose called.
CdsUpperAlarmLimit is using unmanaged resources or memory and must clean up when it's done or there will be a memory leak

Why is calling Dispose() in a finalizer causing an ObjectDisposedException?

I have a NHibernate repository that looks like this:
public class NHibRepository : IDisposable
{
public ISession Session { get; set; }
public ITransaction Transaction { get; set; }
// constructor
public NHibRepository()
{
Session = Database.OpenSession();
}
public IQueryable<T> GetAll<T>()
{
Transaction = Session.BeginTransaction();
return Session.Query<T>();
}
public void Dispose()
{
if (Transaction != null && Transaction.IsActive)
{
Transaction.Rollback(); // ObjectDisposedException on this line
}
Session.Close();
Session.Dispose();
}
~NHibRepository()
{
Dispose();
}
}
When I use the repository like this, it runs fine:
using (var repo = new NHibRepository())
{
Console.WriteLine(repo.GetAll<Product>().Count());
}
But when I use it like this, it will throw an ObjectDisposedException:
var repo = new NHibRepository();
Console.WriteLine(repo.GetAll<Product>().Count());
The easy solution would be to always dipose of the repository explicitly, but unfortunately I don't control the life cycle of some of the classes that use the repository.
My question is, why is the Transaction disposed of already even though I did not explicitly call Dispose()? I'd like to have the repository automatically clean itself up if it was not disposed explicitly.
My question is, why is the Transaction disposed of already even though I did not explicitly call Dispose()?
Perhaps the transaction's finalizer ran first. Remember, finalizers of dead objects can run in any order and on any thread, and need not have been correctly initialized before they are finalized. If you do not understand all the rules of finalizers then learn them all before you attempt to write any more code that uses finalizers. This is one of the hardest things to get right.
It also looks as though you have implemented the disposable pattern incorrectly, and that is going to cause you a world of grief. Read up on the pattern and do it correctly; the finalizer should not be disposing stuff that has already been disposed:
http://msdn.microsoft.com/en-us/magazine/cc163392.aspx
Lose the finalizer. Very few classes in .net need a finalizer; generally, the only .net 2.0-or-later classes which should have finalizers are those whose sole reason for existence revolves around it.
If a class with a finalizer holds an access to some other object, one of three conditions will apply when the finalizer is run:
The other object has already had its finalizer (if any) run; there's no need to dispose it, since it's already been taken care of.
The other object has a finalizer scheduled to run; there's no need to dispose it, since it will be taken care of automatically.
A reference to the other object exists outside of the object whose finalizer is running; this usually means one shouldn't dispose it.
The only time a finalizer should ever take any action to dispose of a manage object is when an outside reference is likely to exist, and the collection of the object being finalized will imply that the other object should be disposed despite the existence of that reference. That's a very rare situation.
You should put GC.SuppressFinalize(this); in your Dispose method otherwise the finalizer will dispose an already disposed object. Also, finalizers are in almost all cases only needed for unmanaged resources
The CLR makes no guarantees with respect to the order that finalizers will be called. It sees a group of unrooted objects (e.g. not reachable from any GC root) and starts calling finalizers. It doesn't matter that you have connections within your object graph. The finalizers can be called in any order. Finalizers are intended to clean up unmanaged resources, not child objects. You need to re-think your API.
You should have a member variable isDisposed that would be set to true by the Dispose() method. Then at the beginning of the Dispose() command just return if it is already set to true. According to .NET whitepapers, Dispose() could be executed multiple times without side effects and this is the way to do it.
Secondly, make the class sealed (the class is not implementing the Dispose pattern properly for inheritance) and put GC.SuppressFinalize(this); right before the isDisposed variable assignment in the Dispose() method.
public void Dispose()
{
if (isDisposed) { return; }
....
GC.SuppressFinalize(this);
isDisposed = true;
}

Categories