What is the object life cycle for an object in .NET?
From what I understand it is:
0) If Static Constructor exists on Object it is called the first time and object of that type is created or referenced
Just as an edge case... you can create objects without using the ctor at all:
class Foo {
public Foo() {
message += "; ctor";
}
string message = "init";
public string Message { get { return message; } }
}
static class Program {
static void Main() {
Foo foo = new Foo();
Console.WriteLine(foo.Message); // "init; ctor"
Foo bar = (Foo)System.Runtime.Serialization.FormatterServices
.GetSafeUninitializedObject(typeof(Foo));
Console.WriteLine(bar.Message); // null
}
}
Here are the steps I know of:
As others already have pointed out, Dispose()
must be called by the user since the runtime won't act on it.
In C#, member initializers are called before the constructor while in VB.NET, they are called after the constructor.
The runtime does not guarantee calling Finalize
at all.
Dispose and Finalize is for cleaning up unmananged resources only. Trying to clean up managed resources in a finalizer by e.g. calling Dispose on inner members will land you in trouble because they may have been finalized already.
I like to keep things simple and just use the finalizer to detect and log a nasty error message telling the developer to go fix the code. Trying to figure out whether it is safe to do the work Dispose
was supposed to do is too easy to get wrong and usually not worth spending cycles on.
Dispose doesn't get called automatically; you need to call it, or use a using block, eg.
using(Stream s = File.OpenRead(@"c:\temp\somefile.txt"))
// Do something with s
The finalizer only gets called by the GC if it exists. Having a finalizer causes your class to be collected in 2 steps; first the object is put in the finalizer queue, then the finalizer is called and the object is collected. Objects without finalizers are directly collected.
The guideline is that Dispose gets rid of managed and unmanaged resources, and the finalizer only cleans up unmanaged resources. When the Dispose method has freed the unmanaged resources it can call GC.SuppressFinalize to avoid the object from living long to be put on the finalizer queue. See MSDN for a correct sample of the dispose pattern.
Here is an example class that uses all the information available in the articles provided here. I have already spent hours testing things out, and this is what works best for me.
/*********************************
* Author: Theofanis Pantelides *
* Date: 23 Jun 2009 *
*********************************/
using System;
using System.IO;
public class MyClass : IDisposable
{
String oFile;
Stream oStream;
public MyClass(String _File)
{
oStream = File.OpenRead(oFile = _File);
// Initialize
}
~MyClass()
{
this.Dispose();
// Destruct
}
public void doSomething()
{
// do Whatever it is you are trying to do
}
#region IDisposable Members
/// <summary>
/// Dispose all resources used by instance of class
/// and update Garbage Collector information
/// </summary>
public void Dispose()
{
if (oStream != null)
{
oStream.Dispose(); // Dispose using built in functions
GC.SuppressFinalize(oStream); // No need for Garbage Collector
}
oStream = null; // Nullify it.
}
#endregion
}
Usage:
using(MyClass mc = new MyClass(@"c:\temp\somefile.txt"))
{
mc.doSomething();
}
You can even use the same declaration twice as it does not exist outside the 'using'.
using(MyClass mc = new MyClass(@"c:\temp\somefile.txt"))
{
mc.doSomething();
}
using(MyClass mc = new MyClass(@"c:\temp\somefile.txt"))
{
mc.doSomething();
}