There are lots of questions about managed vs unmanaged resources. I understand the basic definition of the two. However, I have a hard time knowing when a resource or object is managed or unmanaged.
When I think of unmanaged resources I tend to think of native code that isn't directly part of .NET such as pinvoke or marshaling resources. I would normally think of resources meant to interface to something that will use HW such as a file handle or network connection also being unmanaged.
What about .NET objects that wrap native unmanaged resources such as a FileStream
.
A FileStream
must use unmanaged resources, but when I implement the IDisposable
pattern, should I consider this a managed or unmanaged resources?
I've been assuming thus far that if the object implements IDisposable
, then it is managed. How would I know that IntPtr
should be handled as an unmanaged resoruce?
Managed resources are resources which can be freed up by the garbage collector and unmanaged resources cannot be freed up by the garbage collector for this purpose destructor is required.
However, when you create objects that include unmanaged resources, you must explicitly release those resources when you finish using them. The most common types of unmanaged resources are objects that wrap operating system resources, such as files, windows, network connections, or database connections.
Managed objects are created, managed and under scope of CLR. Unmanaged objects are wrapped around operating system resources like file streams, database connections, network related instances, handles to different classes, registries, pointers, etc.
A
FileStream
must use unmanaged resources, but when I implement the IDisposable pattern, should I consider this a managed or unmanaged resources?
A FileStream is a managed resource.
Managed resources are classes that contain (and must manage) unmanaged resources. Usually the actual resource is several layers down.
I've been assuming thus far that if the object implements
IDisposable
, then it is managed.
Correct.
How would I know that IntPtr should be handled as an unmanaged resoruce?
From the documentation of the API that you got its value from. But do note that in practice, most programmers never deal with unmanaged resources directly. And when you do have to, use the SafeHandle
class to turn an unmanaged resource into a managed resource.
It is pretty straight-forward, you can never accidentally allocate an unmanaged resource. A pinvoke call is required to allocate it, you'd know about it. The term "object" is overloaded, but there is no such thing as an unmanaged object, all objects in a .NET program are managed. You may interop with code written in another language that supports creating objects, like C++. But you cannot directly use such an object, a C++/CLI wrapper is required. Which makes it a managed class that implements IDisposable.
If you work with a poorly documented library then do pay attention when you get an IntPtr back. That's a pretty strong indication that an unmanaged allocation is involved, either a pointer to unmanaged memory or an operating system handle. That library should then also give you a way to release it, if it doesn't otherwise manage it automatically. Contact the owner of the library if you are not sure how to properly deal with it.
It was Microsoft's job to provide managed wrapper classes around all common operating system resources. Like FileStream, Socket, etcetera. Those classes almost always implement IDisposable. The only thing you have to do in your code when you store such an class object in your own class is to implement IDisposable yourself, just so you call the Dispose() method on those object. Or use the using statement if you use them as a local variable in a method.
It is most helpful to think of a "resource" in this context as meaning "something which an object has asked something else to do on its behalf, until further notice, to the detriment of everyone else". An object constitutes a "managed resource" if abandoning it would result in the garbage collector notifying the object of abandonment, and the object in turn instructing anything that was acting on its behalf to stop doing so. An "unmanaged resource" is a resource which is not encapsulated within a managed resource.
If some object Foo
allocates a handle to unmanaged memory, it asks the memory manager to grant it exclusive use of some area of memory, making it unavailable to any other code that might otherwise want to use it, until such time as Foo
informs the memory manager that the memory is no longer needed and should thus be made available for other purposes. What makes the handle an unmanaged resource is not the fact that it was received via an API, but rather the fact that even if all deliberate references to it were abandoned the memory manager would forever continue granting exclusive use of the memory to an object which no longer needs it (and likely no longer exists).
While API handles are the most common kind of unmanaged resource, there are countless other kinds as well. Things like monitor locks and events exist entirely within the managed-code world of .net, but can nonetheless represent unmanaged resources since acquiring a lock and abandoning while code is waiting on it may result in that code waiting forever, and since a short-lived object which subscribes to an event from a long-lived object and fails to unsubscribe before it is abandoned may cause that long-lived object to continue carrying around the event reference indefinitely (a small burden if only one subscriber is abandoned, but an unbounded burden if an unbounded number of subscribers are created and abandoned).
Addendum A fundamental assumption of the garbage collector is that when object X holds a reference to object Y, it is because X is "interested" in Y. In some situations, however, the reference may be held because X wants Y to hold a reference to it even though Y doesn't "care" one way or the other. Such situations occur frequently with notification event handlers. Object Y may want to be notified every time something happens to object X. Although X has to keep a reference to Y so it can perform such notifications, X itself doesn't care about the notifications. It only performs them because of a presumption that some rooted object might care about Y's receiving them.
In some cases, it's possible to use what's called a "weak event pattern". Unfortunately, while there are many weak event patterns in .net, all of them have quirks and limitations due to the lack of a proper WeakDelegate
type. Further, while weak events are helpful, they're not a panacea. Suppose, for example, that Y
has asked long-lived object X
to notify it when something happens, the only existing reference to Y
is the one X
uses for such notification, the only thing Y
does with such notification is to increment a property in some object Z
, and that setting that property modifies nothing outside Z
. Under that scenario, even though object Z
will be the only thing in the universe that "cares" about object Y
, Z
won't hold any sort of reference to Y
whatsoever, and so the garbage collector will have no way of tying Y
's lifetime to that of Z
. If a X
holds a strong reference to Y
, the latter will be kept alive even after nobody's interested in it. If X
only holds a weak reference, then Y
may be garbage-collected even if Z
is interested in it. There is no mechanism by which the garbage collector can automatically infer that Z
is interested in Y
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With