(1 item) |
|
(1 item) |
|
(5 items) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(6 items) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(4 items) |
|
(2 items) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(2 items) |
|
(5 items) |
|
(3 items) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(3 items) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(8 items) |
|
(2 items) |
|
(7 items) |
|
(2 items) |
|
(2 items) |
|
(1 item) |
|
(2 items) |
|
(1 item) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(5 items) |
|
(1 item) |
|
(3 items) |
|
(2 items) |
|
(2 items) |
|
(8 items) |
|
(7 items) |
|
(3 items) |
|
(7 items) |
|
(6 items) |
|
(1 item) |
|
(2 items) |
|
(5 items) |
|
(5 items) |
|
(7 items) |
|
(3 items) |
|
(7 items) |
|
(16 items) |
|
(10 items) |
|
(27 items) |
|
(15 items) |
|
(15 items) |
|
(13 items) |
|
(16 items) |
|
(15 items) |
Given the distinction .NET draws between managed and unmanaged code, it is tempting to think that unmanaged resources are the kinds of things you tend to deal with in unmanaged code. You know the kinds of things - handles, raw pointers to blocks in the unmanaged C++ heap, sockets, and so on.
But if you think about it, that's a bizarrely specific definition. I prefer this much simpler one:
Unmanaged resources are those resources that the CLR doesn't manage for you.
This obviously includes all the items listed above, but is a little more open ended. In particular, it doesn't necessarily preclude those resources that were acquired using a pure .NET API, and which don't have a directly tangible manifestation such as a handle or file. For example, does the CLR manage lock ownership?
Why does this matter? Well this came up due to a discussion over the use of the IDisposable
interface, which is documented thus:
Defines a method to release allocated unmanaged resources.
John Elliot evidently thinks I am wrong to use the C# using
keyword to manage lock acuisition. (You knew I wasn't going to manage going a whole
month without mentioning it...) He says:
My point is that if you use 'using' to call Dispose for some other purpose (like Ian's TimedLock that has been floating around just to infuriate me for the last couple of weeks) then you're doing the wrong thing. You are abusing a system interface because you like the facility that you can get from it.
His opinion here is strikingly different from what a PM on the C# team at Microsoft had to say about me using the
using
statement in this way:
we decided to name it "using" rather than something more specific to disposing objects so that it could be used for exactly this scenario.
:-)
If you use the first, rather narrow definition of an unmanaged resource, then arguably John is right. But if you
use the second, more straightforward definition, then it's clear that locks are unmanaged resources. The CLR just gives me
a couple of low level primitives: Enter
and Leave
. These are to locking what
malloc
and free
(or if you prefer, new
and delete
) are to
memory. Of course memory is one of the things that the CLR does manage, so we are no longer required to free
the memory we allocated.
Locks, however, are entirely our problem - just as much as memory management used to be in the pre-.NET days.
So I think that using
and IDisposable
are appropriate for scope-based management of any
resource that is not managed for you by the CLR. And that emphatically includes lock ownership.
[Update: Philip Haack emailed me, partly to take
me to task for not having implemented comments in my blog yet, but mainly to point out an interesting
conversation he had with Eric Gunnerson on this subject. It's about half way down, in the paragraph starting
"I asked Eric Gunnerson...". Apparently the lock
keyword probably wouldn't even have made it into the
language if using
had been invented earlier, because you can recreate lock
-like semantics
in the way that my TimedLock
does.]