This will be a long write up.
of the cool things about using a language like c sharp is memory
management. In the old days, like in C programming age, you had direct
control over where your data is stored. There are pointers that make
this possible. For super cool developers, having that kind of control is
awesome However, even super experts make mistakes and having that kind
of control may not be a good idea.
is where the memory management of c sharp comes into play. In c sharp,
there is something called as garbage collector. Think of the garbage
collector as a librarian at the...library. You want a book. Instead of
allowing you to pick up the book you want, the librarian will go and get
the book for you. She won't
let you go inside though. She believes that you will mess things up.
However, she is fast and extremely good at her job. She will always get
you the book you want, almost all the time. As long its in the library, you know she will get it for you.
As a library goer, all you need to know is, if the library website says that a book is available, you can bet your expensive computer that she will get it for you. The
garbage collector is like that. A proxy to the memory that your
application needs. She will ensure that your application gets the memory
it wants, as long as it can be made available.
we jump head first into how exactly garbage collector does her job, we
need to look at the types. Yes, you remember that you have two types –
value and reference types. Value types are stored in the stack. That
means, the moment the method comes to an end, the stack is completely
cleared. Stack is cleared by the CLR (not the above mentioned garbage
other type I.e. reference types are the ones that go to the heap. The
heap is the domain of the garbage collector. Garbage collector rules
over the heap. The garbage collector uses what is called as 'mark and
this works is like this. Garbage collector understands that it cannot
be clearing up memory all the time. That's because garbage collector
knows that cleaning memory also has a performance hit.
Which is why, garbage collector becomes active only when there no new
memory to assign to objects asking for it. As long as there is room to
give for new objects, it stays put.
the memory is full (or about to become full) it becomes active. At this
point, the garbage collector beings 'marking' object in the memory. The
garbage collector goes through the items in the memory and finds
'living' items. A living item is an item that is referenced by what is
called a 'root' item. Root item means, it is either a static field or a
method parameter or a local variable or a CPU register. Once all the
items have been checked (and marked if they are living), the garbage collector will remove all the 'dead' items from the memory, freeing up memory.
live items are all moved to be together. This is the packing part of
the garbage collector activity. The live items are all packed to one
side of the memory. These live items are 'promoted' by being assigned a
higher generation. The rest become generation 0, and they are cleared up. I just realized that this is the same thing I said before about 'dead' items.
move on to something that is not exactly possible by garbage collector.
You see, garbage collector works best with managed items.
Unfortunately, an application cannot be built with managed items or
managed resources only. For instance, an object of your custom type is a
managed item or managed resource. That is the something garbage
collector handles really well. No problems there. When
you use a file in your program that file is an 'unmanaged' item or
'unmanaged' resource. Garbage collector cannot work with that since the
file itself is stored outside, somewhere else. Not in the actual memory
that comes under the purview of garbage collector.
That means, the onus on handling with these unmanaged resources
is on you. That means, you no longer have the option of depending on
garbage collector for your memory related dirty work. It is now up to
you to handle these issues. With unmanaged resources anything can go
wrong. The file you are writing over a network, may suddenly become
unavailable. You cannot let your application crash.
this purpose, c sharp gives you something called 'finalizer'. You
specify a method as finalizer. In this method you do all the freeing of
unmanaged resources. And then, you are free to do other activities on
your unmanaged resources. For instance, you are writing to a file. Then,
after you are done, you want to delete it. However, unless the file has
been properly closed, delete won't happen. That
is where finalizer comes into play. You will write the file close code
in the finalizer. Then, thanks to the finalizer, your file is definitely
closed, and you are now free to delete that file.
Now, the tricky thing about finalizers is that, you cannot call them. Yep, that's right. It's disappointing
but this is another way of c sharp making sure your application remains
robust. However, the finalizer is called by garbage collection when it
becomes active. This ensures that all resources are released and that
means, once the garbage collection has occurred, you can be sure that
the finalizer has been called. There is also the minor scenario where
you try to do a unmanaged resource operation such as deleting a file but
the finalizer is not done yet. That is why you can even wait for
finalizers to finish. This way, you can be definitely sure that yes your
unmanaged resource is handled well.
However, here is that problem. What if the garbage collection never happens? That means the finalizer was never called, and that
means your unmanaged resource is still doing something. Your
application will fail. You can call garbage collector manually all the
time. That will slow down your application like a crazy person.
order to ensure that you don’t place all your bets on garbage
collection, c sharp provides you with something else. It gives you the
IDispose interface. It contains one method (called as Dispose) which
will, the moment it is called, it will free all unmanaged resources
Now (yes, this is going on and going but memory management is a complicated topic), what if something
goes wrong before you use the Dispose method? That is where you use old
try/finally concept that grabs unexpected errors. So, we are looking at
a combination of try and catch and then calling dispose to make sure
that the unmanaged resource will never mess with your program flow.
Now, use those three – try finally and
dispose – is good but it increases the amount of code you write. When
you are working with many, and I mean many unmanaged resources, you will
have to write this again and again. If you have a hundred files, the
code keeps growing and growing. Since this is a frequently
done thing, c sharp (of course) has a better solution. The solution is
the 'using' statement. The using statement will bundle all the three
into a single package. That way, you can code less and get done more.
you want to catch exceptions, you may also choose to include a catch in
the above sequence, although using itself cannot be modified to include
I am going to have to skip the code for this blog post. I am yet to
blog about files, and we will revisit the topic of unmanaged resources
Follow me on twitter, facebook and instagram for more updates. Thanks!