Hi I'm new in this great community and I have my first question. Hope this one is in the right place (and I hope my english is correct):
I'm novice developer and I have to improve a C# Application, so I've found this code and I want to know if this is the right way to do it:
ObjClass obj = new ObjClass();
obj.SomeText = TextBox1.Text;
obj.SomeNumber = Convert.ToInt32(TextBox2.Text);
The definition of ObjClass is the following:
using System;
namespace SomeObject
{
public class ObjClass : IDisposable
{
public string SomeText { get; set; }
public int SomeNumber{ get; set; }
public void Dispose()
{
GC.SuppressFinalize(this);
}
}
}
Then after using the object the code to finalize or disposing the objecto is the following:
if(obj.SomeNumber != null)
{
//doing something else
obj.Dispose();
}
If a class is disposable the best way to make sure it gets disposed is to use a using block.
using(var foo = new ObjClass())
{
// do something
}
This will ensure that the object is disposed even if an exception occurs.
The correct way would be not to write a Dispose function at all. At best you're just tying up the GC, preventing it from freeing your object until it invokes it on the GUI thread (slowing it down) and gets back confirmation that it has run. At worst you write it as bad as you did and end up with potential memory leaks.
Now if you handle native memory or resources directly in your object (and it's rare, you can avoid handling most of them and leave it to .NET), the correct way of writing a finalizer (ie the part you're missing!) is:
public class Base: IDisposable
{
private bool disposed = false;
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
disposed = true;
}
}
// Use C# destructor syntax for finalization code.
~Base()
{
// Simply call Dispose(false).
Dispose (false);
}
}
Where your code simply prevents finalizers from running, this code either calls Dispose(false) in your finalizer (ie when the GC determines that your object is useless and tries to free it) or Dispose(true) when you call Dispose() yourself (and then prevents the GC from calling the finalizer so you don't dispose twice).
As to how you use it, this is the correct way:
using(var obj = new Base())
{
// do whatever you want
// obj.Dispose() will automatically be called at the end of scope
}
Which is functionally equivalent to:
try
{
var obj = new Base();
// use the object
}
finally
{
// always called, even during exception stack unwinding
obj.Dispose();
}
And again, the correct way is not to write a Dispose. Every time you are required to do it, it's a failure of the framework to provide you with the right tools to stay in the managed world. These instances are fewer and fewer nowadays.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With