Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do we have Unmanaged resources in C#?

I had a discussion with my friend about managed and unmanaged resources in c#.

According to my friend:

1.a) Every object in C# is managed and there is nothing like unmanaged object or resource when we code in C#. Unmanaged resource concept comes only with C++.

1.b) Whether we have managed or unmanaged resource in C++ we need to free it explicitly. Since we have automatic garbage collector in C# we need need not think about managing resources.

According to me:

2.a)If we do not have unmanaged resource then why do we need a finalizer or Dispose method in C#?

2.b)Garbage collector only has information about allocated memory and not about the state of the resources. Therefore we need to use dispose method to release resources in C#.

I need help in understanding which of the above arguments are correct and information about unmanaged resource in c#, whether they exist or not?

Thanks in Advance.

like image 683
Vinod Menezes Avatar asked Jun 17 '11 08:06

Vinod Menezes


2 Answers

No, it is impossible to write a C# program without using unmanaged resources. It is inevitable, a C# program runs on an operating system that is 100% unmanaged. If you use a file then you use an operating system resource. A network connection. A thread. The console. Etcetera, all very much unmanaged resources.

That fact is however hidden pretty well in .NET. The framework library has nice wrapper classes for these native objects. FileStream, Socket, Thread, Console, etcetera. Memory is an operating system resource too, the garbage collector is a wrapper around it.

Of all of these resources, only the memory resource is truly automatically managed. The rest of them get some measure of help by virtue of their wrapper class. Their finalizer is the key, it releases the operating system resource when it is called. That's pretty close to automatic, the garbage collector notices that the wrapper class object is no longer referenced anywhere so it releases it, the finalizer then ensures that the unmanaged resource is released as well.

That usually works well, you can often ignore these implementation details in your code. Many programmers do.

There is a problem with finalizers though, they take a while to start running. It takes a garbage collection to get them started, that can take anywhere from a handful of milliseconds to minutes. It is unpredictable, it depends on the rate in which you consume memory in your code. If you don't use a lot of it then it will take a long time.

You cannot always afford to wait that long for an unmanaged resource to get released. A file is a good example. When you open one to read data from the file then you really should close the file when you're done reading. If you wait until the finalizer gets that job done then you run the risk of your program failing when it needs to open the file again, some time later. You might have locked yourself out by opening the file with FileShare.None, it locks your own code out as well. No big deal: you call Close() to close the file when you're done reading. To be sure it gets closed, you should put the Close() call in a finally block so it runs even if the code aborts due to an exception. In effect, you run the finalizer code explicitly.

A more serious case is an operating system resource that is very expensive. Good examples of those are bitmaps, they can take a lot of unmanaged memory, or database connections, there is a pool for them that by default only contains 100 of them. For these, you can get yourself well into a situation where letting the finalizer take care of releasing the resource just doesn't work because it takes too long. Your program dies on an exception before the finalizer can run. Usually pretty hard to diagnose because that tends to only happens when your program is under load. Always hard to debug problems that occur when lots of things are going on, on a machine that is not on your desktop.

The .NET designers recognized this need and designed the IDisposable interface. Its Dispose() method was designed to run the code that normally is run by the finalizer, giving you a way to explicitly releasing a resource rather than waiting for the garbage collector to get around to it. And the language designers jumped on that bandwagon by adding the using keyword to their language, ensuring that IDisposable.Dispose() is automatically called.

Using using or Dispose() in your code for any object that implements IDisposable is optional, as explained above, but considered vital by many .NET programmers. Mostly because everybody started .NET programming without it and ran into a problem sooner or later when their programs got big. It is even prescribed on classes where calling Dispose() makes no sense, like MemoryStream. And causes mental anguish when a class should implement IDisposable but doesn't, like Thread. Or when a class implements both Dispose and Close (it makes no difference). For comparison, Java has the same considerations but doesn't have IDisposable.

like image 50
Hans Passant Avatar answered Oct 03 '22 15:10

Hans Passant


Objects created in .NET are managed code but your objects can hold a reference to unmanaged ressources. Garbage collector (GC) makes sure any memory allocated on the managed heap is cleaned up after it is no longer needed. However, while the garbage collector is great at making sure that memory does not leak, it doesn’t have any knowledge about other resources that need to be freed. For instance, the garbage collector doesn’t know how to close a file handle or how to release memory allocated outside of the managed heap with an API such as CoAllocTaskMem.

Objects that manage these types of resources must ensure that they are released when they’re no longer needed. You can accomplish this by overriding the Finalize method of System.Object, which lets the garbage collector know that the object would like to participate in its own cleanup (in C# you use the C++ destructor syntax, ~MyObject, rather than directly overriding the method). If a class has a finalizer, then before objects of that type are collected the garbage collector will call the object’s finalizer and allow it to clean up any resources that it may be holding onto.

One problem with this system is that the garbage collector does not run deterministically and, as a result, your object may not be finalized for a long time after the last reference to it has gone away. If your object holds onto an expensive or rare resource, such as a database connection, this may not be acceptable. For instance, if your object has 1 of only 10 available connections open, it should release that connection as soon as possible, rather than waiting for the garbage collector to call the finalize method.

For that you have a IDisposable interface that you should implement. Read more about it.

like image 44
Tomasz Jaskuλa Avatar answered Oct 03 '22 15:10

Tomasz Jaskuλa