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?
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.
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.
Correct.
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 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 asFoo
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, thatY
has asked long-lived objectX
to notify it when something happens, the only existing reference toY
is the oneX
uses for such notification, the only thingY
does with such notification is to increment a property in some objectZ
, and that setting that property modifies nothing outsideZ
. Under that scenario, even though objectZ
will be the only thing in the universe that "cares" about objectY
,Z
won't hold any sort of reference toY
whatsoever, and so the garbage collector will have no way of tyingY
's lifetime to that ofZ
. If aX
holds a strong reference toY
, the latter will be kept alive even after nobody's interested in it. IfX
only holds a weak reference, thenY
may be garbage-collected even ifZ
is interested in it. There is no mechanism by which the garbage collector can automatically infer thatZ
is interested inY
.