Microsoft Exam 70–483: Programming in C# — Objective 2.6: Manage the object life cycle

Luis Felipe (LuisDev)
4 min readAug 20, 2019

--

Hello, folks!

In this story, the Objective 2.6: Manage the object life cycle will be discussed! Hope you enjoy it!

In the last story, the Objective 2.5: Find, execute, and create types at runtime by using reflection was presented.

All the code for the certification series can be found here.

Understanding the Garbage Collector

Before getting into the details of unmanaged resources management, it is worth giving an introduction to how does memory management works and which benefits does the CLR (Common Language Runtime) brings to the table regarding that management.

When writing code, we trust the CLR to handle the memory allocation of the objects and variables we create. A memory allocation is created for our object, and most of us do not even care how it is treated behind the stage.

The heap receives the objects created in our code. But hey, what if we start allocation too many objects on the heap? What about OutOfMemoryException’s?

For that issue, the Garbage Collector takes place to solve. It is the responsible for the heap management. When objects are no more needed (referenced), the garbage collector will reclaim the memory from heap so more objects can be allocated.

The heap works with three “regions”, which are called “generations”. There are the gen0, gen1 (the first two are together at the same segment) and gen2. All new objects are allocated at gen0, and once memory allocation at that generation reach a dynamic threshold, a garbage collection is performed, promoting the objects (that are still being referenced) to the gen1 and freeing space at gen0. Garbage collector affects the gen and its previous generations, so a gen1 collection is performed on both gen0 and gen1.

After the memory freeing, a compacting operation is performed. It means to move objects (and keep the right memory references) to fill the generation freed spaces.

Large objects (more than 85,000 bytes) are allocated in gen 2 heap segment. Due to the performance issues it can bring to compacting large objects, large objects are not compacted.

For more information regarding Garbage Collector and performance stuff, I highly recommends the book Writing High-performance .NET Code, authored by Ben Watson.

Managing unmanaged resources

File handles, network connections (HttpClient? haha) and database connection involves unmanaged resources.

Even though for strings and classes instances allocation and disposing is automatically handled for you by the CLR, the same can not be said for the unmanaged resources.

Implement IDisposable, including interaction with finalization

A better approach for cleaning up resources on classes with unmanaged resources is to implement the Dispose pattern.

Basically, your class would implement IDisposable interface and derive a SafeHandle field. The SafeHandle provides you with a finalizer, so you do not have to implement your own.

The Dispose(boolean) method contains your overload implementation of the Dispose method, which would “play” with a boolean field (on the below code, it is “disposed) to check if the resources were released.

In the above code, GC.SupressFinalize tells the CLR to not invoke the Finalizer method, thus reducing the object lifetime that would be extended due to using the Finalizer method (which will be explained later in the article).

Manage IDisposable by using the Using statement

By using the using statement with a class that implements IDisposable, the Dispose method is called at the statement end. It is the recommended way to use IDisposable classes, so you are freed from the responsibility of calling Dispose once you are finished using the class.

In the above code, use a breakpoint to check that the Dispose method is called at the end of the using statement,

Manage finalization and garbage collection

Even thought the Dispose Pattern is the better approach, you can implement your own Finalizer method.

Before your object is ready to be reclaimed, your object will execute the method Finalizer. Its function is to perform cleanup operation prior to the garbage collection.

In the above code, the Garbage Collection is performed manually. Since its reference is set to null, its Finalizer will be queued up to be executed once the WaitForPendingFinalizers method is called.

However, using Finalizers mostly is not considered a good practice. It increases the lifetime of the object by queueing it to perform the finalization code, when its allocation could be freed directly if it internally had cleaned up its unmanaged resources.

That’s it for now! I hope that you learned at least something useful whether you are studying focused on clearing the certification exam or just looking for learning more about C#.

See you in the next Story, where I will discuss the Objective 2.7: Manipulate strings.

PS: If you find this Story useful, I invite you to hit the Clap button. Also, I would be happy to see you as my new follower!

--

--

Luis Felipe (LuisDev)

3x Microsoft MVP, 9x Microsoft Certified, .NET and Azure Consultant