Breaking News

The Life and Time of an object In C#

Lets see, what happens when you create and destroy an object. Here we have created an object like this:
 
TextBox msg=new TextBox(); // TextBox is a reference type
 
From your point of view, the new operator looks atomic, but underneath, object creation is really a two-phase process. In the first step, the new operation has to allocate some raw memory from the heap.
 
You have not any control over this phase of an object’s creation. In the second step, the new operation has to convert the raw memory into an object; it has no initialize the object. You can control this phase this by using a constructor.
 
Once you have created an object, you can access its members by using the dot operator. e.g.
 
Msg.Text= “eBIZ.com Pvt. Ltd.”;
 
You can make other reference variables refer to the same object:
 
TextBox msg1=msg;
 
How many references can you create to an object? As many as you want! The runtime has to keep track of all references. If the variable msg disappears, other variables msg1 might still exist. Therefore, the lifetime of an object can’t be tied to a particuler reference variable. An object can only be destroyed when all the references to it have disappeared.
 
Like object creation, object destruction is also a two phase process. In the first step, writing a destructor and in the second step, the raw memory has to be given back to the heap; the memory that the object lived in has to be deallocated. Once again, you have no control over this phase.
 
The process of destroying an object and returning memory back to the heap is known as garbage collection. The given picture shows the stages in the life of memory and objects.
 
img
 
Memory and Object Lifecycle
 
Writing Destructors
 
You can use a destructor to perform any tidying up required when an object is garbage collected. The syntax for writing a destructor is a tilde(~) followed by the name of the class.e.g. here is a class that’s counts the number of live instances by incrementing a static count in the constructor and decrementing a static count in a destructor:
 
class Tally
{
private static int instanceCount = 0;
 	public Tally() // Constructor
 	{
 		instanceCount++;
 	}

 	~Tally()  // Destructor
 	{
 		instanceCount--;
 	}

 	public static int InstanceCount()
 	{
 		return instanceCount;
 	}
}
 
Important Restrictions over Destructor
 
• You can’t declare a destructor in a struct since it is a value type that lives on the stack and not the heap. So the garbage collection doesn’t apply.
 
Struct abc
{
 	~abc(){ … } // compile time error
}
 
• You can’t declare an access modifier for a destructor, because you never call the destructor yourself(garbage collector deos).
 
Public ~abc() { … } // compile time error
 
• You never declare a destructor with parameters.
 
~abc(int parameter) { … } // compile time error
 
• The compiler automatically translates a destructor into an override of the Object.Finalize method:
 
Class abc
{
	~abc() { … }
}
 
here is the translation:
 
Class abc
{
 	protected override void Finalize()
 	{
 		try { … }
 		finally 
{ 
base.Finalize();
}
 	}
}

 
To compiler generated Finalize method contains the destructor body inside the try block followed by a finally block that calls the base class Finalize. This ensures that a destructor always calls its base class destructor. Its important to realize that only the compiler can make this translation. You can’t override Finalize yourself and you can’t call Finalize yourself.
 
What is garbage collection?
 
In computing, garbage collection (also known as GC) is a form of automatic memory management. The garbage collector attempts to reclaim the memory used by objects that will never be accessed again by the application. Garbage collection was invented by John McCarthy around 1959 to solve the problems of manual memory management in his recently devised Lisp programming language.
 
Many computer languages require garbage collection, either as part of the language specification (e.g. Java, C#, Dylan) or effectively for practical implementation (e.g. formal languages like lambda calculus); these are said to be garbage-collected languages.
 
Other languages were designed for use with manual memory management, but have garbage collected implementations (e.g., C, C++). In either case, it is easier to implement garbage collection as part of the language’s compiler and runtime system. The garbage collector will almost always be closely integrated with the memory allocator.
 
How does the garbage collector run?
 
Garbage collector runs in its own thread and runs only when other threads are in a safe state(suspended). When it runs, it needs to move objects and update object references:
 
• It build a graph of all reachable objects, any object isn’t in this grpah consider unreachable.
 
• It checks to see the unreachable objects require finalization(destructor). It will place it in freachable queue(pronounced as F-reachable) if it does.
 
• Remaining unreachable objects are deallocated by moving reachable objects down the heap, thus defragmenting and freeing memory at the top of the heap. While it moves reachable objects, it also updates any references to the objects.
 
• Now, it allows other threads to resume.
 
• The freach queue is finalized in a separate thread.
 
Recommendations
 
Writing classes with destructors adds complexity to your code and to the garbage collector process which may result making your program run more slowly. So it is recommend to try to avoid using destructors by all mean necessary except when you really need them (consider a using statement instead). Another is to ensure that each destructor reclaims one resource and nothing else.
 
Resource Management
 
Sometimes it’s inadvisable to release resource in a destructor; some resources are just too valuable and too scarce to lie around unreleased for arbitrary lengths of time. In the situations, your only option is to release the resource yourself with disposal method that disposes resources. If a class has a disposal method, you can call it explicitly and control when the resource is released.
 
The disposal method pattern
 
TextReader class from the System.IO namespace contains a virtual method called Close(). The StreamReader and String Reader classes both drive from TextReader and both override the Close method:
 
class ResourceMgmt
{
public void DoSomething()
{
TextReader reader = new StreamReader(filename);
string line;
while ((line = reader.ReadLine()) != null)
{
Consle.WriteLine(line);
}
reader.Close();
}
}
 
It’s important to call Close when you have finished with reader to release the file handle(and encoding) resources. However, it isn’t exception-safe. If the call to ReadLine or WriteLine throws exception, the call to Close will not happen!
 
Exception-safe disposal
 
One way to ensure that disposal method always call, regardless of whether there is an exception is to call it inside a try…finally block:
 
class Resource
{
public void DoSomething()
{
TextReader reader = new StreamReader(filename);
try
{
string line;
while ((line = reader.ReadLine()) != null)
{
Consle.WriteLine(line);
}
}
finally
{
reader.Close();
}
}
}
 
However, it has several drawbacks that make it a less than ideal solution:
 
• It quickly get unwieldy if you have to dispose of more than one resource(nested try and finally blocks)
 
• In some cases you might have to modify the code(reorder the declaration of resource reference, remember to initialize the reference to null and remember to check the reference isn’t null in the finally block).
 
• The solution is hard to understand and must be repeated everytime.
 
• The reference to the resource remains in scope after the finally block which means you can accidentally use the resource after it has been release.
 
The using statement is designed to solve all these problems!
 
The using statement
 
using (type variable = initialization) embeddedStatement
 
such using statement is precisely equivalent to:
 
public void ReturnResource()
{
//type variable = initialization;
try
{
//embeddedStatement
}
finally
{
if (varaible != null)
{
 			((IDisposable)variable).Dispose();
}
}
}
 
This equivalence means that the variable you declare in a using statement must be of a type that implements IDisposable interface which live in System namespace and contains just one method called Dispose:
 
namespace System
{
interface IDisposable
{
void Dispose();
}
}
 
You can use a using statement as a clean, exception-safe, robust way to ensure that a resource is always automatically released, you just need to make sure that:
 
• The class containing the diposal method(Close() for TextReader) implements the IDisposable interfaces(as TextReader does).
 
• The class implements Dispose to call the disposal method(TextReader.Dispose() calls TextReader.Close()):
 
abstract class TextReader : IDispoable
{
public virtual void Dispose()
{
//call Close()
}
public virtual void Close()
{
}
}
 
Here is the best way to make sure that you r code always calls Close ona TextReader:
 
using (TextReader reader = new StreamReader(filename))
{
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
 
This approach sloves all of the problems that existed in the manual try…finally solutions:
 
• Scales well if you need to dispose of multiple resources.

• Doesn’t distort the logic of the program code.

• Nicely abstracts away the problem and avoid repetition.

• Is robust.

 
Adapting to IDisposable
 
It’s instructive to consider how you could have used a using statement to ensure that it always call TextReader.Close() if the TextReader class didn’t implement the IDisposable interface:
 
struct AutoClose : IDisposable
{
private readonly TextReader target;
public void AutoClosing(TextReader target)
{
this.target = target;
}
public TextReader GetTextReader()
{
return target;
}
public void Dispose()
{
target.Close();
}
}
 
• AutoClosing doesn’t extend the TextReader class. This avoids the need to replicate all the TextReader constructors inside AutoClosing struct.
 
• AutoClosing isn’t designed to be a base class and doesn’t extend a class. You want the memory deallocated as soon as it goes out of scope. It is best implemented as a struct rather than a class.
 
You can rewirte the GetTextReader accessor method as a read-only property:
 
using(AutoClosing safe = new AutoClosing(new StreamReader(filename)))
{
TextReader reader = safe.GetTextReader();
string line;
while((line = reader.ReadLine() != null)
{
Console.WriteLine(line);
}
}
 
Notice how the reader variable is still in the scope of using statement!
 
Calling a disposal method from a destructor
 
The trade off in deciding whether to use destructors or disposal methods is this: A call to a destructor will happen but you just don’t know when, while you know exactly when a call to a disposal method happens but yo ujust can’t be sure that it will happen because you might forget to call the method! So it is possible to ensure that a disposal method is always called by having “backup”:
 
class Example : IDisposable
{
private Resource scarce;
private bool disposed = false;
~Example()
{
Dispose();
}
public virtual void Dispose()
{
if (!disposed)
{
try
{
//release scarce resource here
}
finally
{
disposed = true;
GC.SuppressFinalize(this);
}
}
}
public void SomeBehavior()
{
CheckIfDisposed();
}
private void CheckIfDisposed()
{
if (disposed)
{
throw new ObjectDisposedException("Example");
}
}
}
}
 
• The class implements IDisposable

• The Dispose method is public and can be called at anytime.

• The Dispose method can be safely called mulitple times.

• The destructor calls Dispose()

• The Dispose method calls GC.SuppressFinalize to stop the garbage collector from needlessly calling the destructor. It’s optional!

• All the regular methods of the class check to see whether the object has alreaady been disposed. If it has, they throw an exception.

 
 

Check Also

Errors in C#

There are three types of errors in C# that can be occur in your application. …