473,387 Members | 3,810 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

IDisposable - beyond Memory Management

There an ongoing discussion between a colleague and myself about the
usefulness of the IDisposable pattern beyond the reclamation of unmanaged
resources. The discussion is somewhat lengthy so I will distill it here.

The core of his argument started with his statement:

"There is no gain in performance, maintainability or otherwise by
implementing the Dispose method if unmanaged resources are not involved."

I focused particularly on the "unless unmanaged resources are involved."
rather than on "No gain in performance" ... Maintainability is a arguable
point. My thinking is that the pattern can be useful for state maintenance
issues at the end of an object's lifetime and not necessarily related to
memory reclamation.

My counter argument was based on the implementation of the
System.Transactions.TransactionScope type in the .Net 2.0 BCL that
essentially defers the execution of the Rollback or Commit of the
Transaction* (as well as context maintenance of the ambient Transaction) to
the Disposal of the scope instance. They chose not to design the type with
BeginScope() and EndScope() methods but instead used the dispose pattern. I
also point out the article by Stephen Toup and his use of IDisposable in his
Scope<Ttype. Of course I went into a lot more detail there. The entire
discussion between us was quite interesting and I have no problems posting
it if anyone out there would like to read it.

I ended my first rebuttal with the following paragraph:

"Instances of System.Transactions.Transaction types may be elevated from LTM
transactions to Enterprise Services DTC Transactions that utilize unmanaged
resources that may need to be reclaimed. Quite apart from this fact though,
the implementation of the TransactionScope type and it's affinity to and
reliance on the dispose pattern for the proper execution of its core
function, unrelated to unmanaged resources or the deterministic reclamation
of those resources most clearly illustrates my point that the Dispose
Pattern's usefulness can exceed memory management."

I just wanted to get feedback from the community about there thoughts on
this?

Cordell Lawrence
Teleios Systems Ltd.

Nov 26 '06 #1
12 2410
"Cordell Lawrence (News Group)" wrote:
"There is no gain in performance, maintainability or otherwise by
implementing the Dispose method if unmanaged resources are not involved."
There are plenty of uses for IDispose that don't involve unmanaged
resources:

* Saving and restoring the cursor, in a GUI app.
* Saving and restoring thread priority.
* Benchmarking code fragments.
* Emitting close tags (or matching braces, or whatever).
* Automatically calling ResumeLayout and the like.

Basically, any time a 'begin' action must be paired with an 'end'
action, a `using` statement makes for smaller, less cluttered code ...
and guarantees that you won't forget the end action.

--

..NET 2.0 for Delphi Programmers
www.midnightbeach.com/.net
What you need to know.
Nov 26 '06 #2
Jon Shemitz <jo*@midnightbeach.comwrote:
"Cordell Lawrence (News Group)" wrote:
"There is no gain in performance, maintainability or otherwise by
implementing the Dispose method if unmanaged resources are not involved."

There are plenty of uses for IDispose that don't involve unmanaged
resources:

* Saving and restoring the cursor, in a GUI app.
* Saving and restoring thread priority.
* Benchmarking code fragments.
* Emitting close tags (or matching braces, or whatever).
* Automatically calling ResumeLayout and the like.

Basically, any time a 'begin' action must be paired with an 'end'
action, a `using` statement makes for smaller, less cluttered code ...
and guarantees that you won't forget the end action.
I don't know - I think all of those somewhat abuse the documented
purpose of IDisposable.

I can see that it's a convenient way of getting try/finally behaviour,
but none of the above really feels like an action which would normally
be called Dispose, or which fits in with any of the documentation
around IDisposable.

Put it this way: I might use it for convenience within an internal set
of classes, but if I were writing a library I wouldn't implement
IDisposable on something that wasn't in *some* way freeing a resource.
(In my MiscUtil library I have locks where Dispose releases the lock
acquired at the start of the using block - and even that feels slightly
tenuous to me.)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 26 '06 #3
"Jon Skeet [C# MVP]" wrote:
* Saving and restoring the cursor, in a GUI app.
* Saving and restoring thread priority.
* Benchmarking code fragments.
* Emitting close tags (or matching braces, or whatever).
* Automatically calling ResumeLayout and the like.

Basically, any time a 'begin' action must be paired with an 'end'
action, a `using` statement makes for smaller, less cluttered code ...
and guarantees that you won't forget the end action.

I don't know - I think all of those somewhat abuse the documented
purpose of IDisposable.

I can see that it's a convenient way of getting try/finally behaviour,
but none of the above really feels like an action which would normally
be called Dispose, or which fits in with any of the documentation
around IDisposable.

Put it this way: I might use it for convenience within an internal set
of classes, but if I were writing a library I wouldn't implement
IDisposable on something that wasn't in *some* way freeing a resource.
I do see your point, but I'm not really sure how valid it is, at least
in the context of C# and the `using` statement, where you don't
actually see a Dispose() call. (Languages like Delphi for .NET that
lack a `using` statement are a different story.)

The way I see it, implementing IDispose in these cases just means that
you can use a `using` statement to make your code smaller and less
cluttered. I admit there is a certain amount of semantic violence, but
there are three reasons I don't think that matters, here. A) Semantic
violence matters where there's a possibility of confusion, which I
don't think is the case, here. I would, in fact, argue that the
smaller code is clearer. B) There's already a certain amount of
fuzziness around the IDispose pattern. with things like streams
exporting Close methods instead of Dispose methods. C) Some of the
other system patterns are used pretty loosely, like IEnumerable, with
its special casing for arrays, classes that implement GetEnumerator
but not IEnumerable, and iterators that don't implement Reset, &c.

Besides, I think I can argue with a straight face that the tiny little
IDisposable class that one creates for all the examples above
constitute a sort of managed resource that needs to be freed - that
you are creating a resource that frees you from the need to explicitly
code your 'end' action.

--

..NET 2.0 for Delphi Programmers
www.midnightbeach.com/.net
What you need to know.
Nov 26 '06 #4
Jon Shemitz <jo*@midnightbeach.comwrote:
Put it this way: I might use it for convenience within an internal set
of classes, but if I were writing a library I wouldn't implement
IDisposable on something that wasn't in *some* way freeing a resource.

I do see your point, but I'm not really sure how valid it is, at least
in the context of C# and the `using` statement, where you don't
actually see a Dispose() call. (Languages like Delphi for .NET that
lack a `using` statement are a different story.)
If I write a library, it doesn't matter whether I write it in C# or not
- it could be used in a different language (eg Delphi.NET) which
*doesn't* have a using statement.
The way I see it, implementing IDispose in these cases just means that
you can use a `using` statement to make your code smaller and less
cluttered. I admit there is a certain amount of semantic violence, but
there are three reasons I don't think that matters, here. A) Semantic
violence matters where there's a possibility of confusion, which I
don't think is the case, here. I would, in fact, argue that the
smaller code is clearer.
Where it's present - but if you end up calling Dispose() explicitly
from other languages, surely that would cause confusion. That's why I
made my comment about the difference between using it effectively for
private use and exposing it as part of a public class.
B) There's already a certain amount of
fuzziness around the IDispose pattern. with things like streams
exporting Close methods instead of Dispose methods.
Not usually "instead of" - "as well as". Close() is there for the sake
of familiarity with previous APIs, IMO.
C) Some of the
other system patterns are used pretty loosely, like IEnumerable, with
its special casing for arrays, classes that implement GetEnumerator
but not IEnumerable, and iterators that don't implement Reset, &c.
That's certainly true.
Besides, I think I can argue with a straight face that the tiny little
IDisposable class that one creates for all the examples above
constitute a sort of managed resource that needs to be freed - that
you are creating a resource that frees you from the need to explicitly
code your 'end' action.
You're clearly better able to maintain a straight face than I am :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Nov 26 '06 #5
Guys, thank you for all the valuable input. Let me now add my two cents:

The official (and much bloged) documented purpose of IDisposable revolves
around the management of memory (unmanaged and disposable managed instances)
and advice on the proper use of the pattern and Finalizers.

Facts:
1. IDisposable.Dispose() is just a normal method, it has no special meaning
to the runtime
2. IDisposable.Dispose() must be called explicitly by the developer
3. The .NET 'using' syntax is a little more than a syntactic sugar
- It guarantees that the Dispose() method is called at the end of the
using scope
-*And! When using this construct the compiler ensures that the 'using
variables' cannot be modified either directly or indirectly through
passing it as out or ref parameters to other method anywhere within the
using scope

To me, these are all points for this pattern being used for more that memory
clean up, and this is evidenced by the implementation of for example
System.Transactions.TransactionScope. Most of the Dispose() method of the
TransactionScope type deals with maintaining State (on the ThreadStatic
variables that maintain info about the current Transaction etc.)

Check out the following link where Stephen Toub uses the properties of this
pattern to implement his Scope<Ttype.
http://msdn.microsoft.com/msdnmag/is...s/default.aspx

I find it interesting that designers of both types chose the following:
using ( Scope<objectscope = new Scope<object>() )
{
// code that is sensitive to the scope
}
As opposed to:
Scope<objectscope = new Scope<object>();
scope.Begin();
// code that is sensitive to the scope
scope.End();

I mean beyond the syntactic brevity, it seems like it was a conscious choice
to use the dispose pattern in this way. I mean you could argue that
Transactions and the generic T in the scope may implement IDisposable and
so, in keeping with good design the designers decided use the dispose
pattern and will recursively call Dispose() on its disposable members, but I
find that hard to swallow.

As for the semantic confusion, I believe that this exists not because of the
Naming of the method and interface but its documentation and the context in
which this pattern is usually referred to.

Cordell Lawrence
Teleios Systems Ltd.
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
Jon Shemitz <jo*@midnightbeach.comwrote:
Put it this way: I might use it for convenience within an internal set
of classes, but if I were writing a library I wouldn't implement
IDisposable on something that wasn't in *some* way freeing a resource.

I do see your point, but I'm not really sure how valid it is, at least
in the context of C# and the `using` statement, where you don't
actually see a Dispose() call. (Languages like Delphi for .NET that
lack a `using` statement are a different story.)

If I write a library, it doesn't matter whether I write it in C# or not
- it could be used in a different language (eg Delphi.NET) which
*doesn't* have a using statement.
>The way I see it, implementing IDispose in these cases just means that
you can use a `using` statement to make your code smaller and less
cluttered. I admit there is a certain amount of semantic violence, but
there are three reasons I don't think that matters, here. A) Semantic
violence matters where there's a possibility of confusion, which I
don't think is the case, here. I would, in fact, argue that the
smaller code is clearer.

Where it's present - but if you end up calling Dispose() explicitly
from other languages, surely that would cause confusion. That's why I
made my comment about the difference between using it effectively for
private use and exposing it as part of a public class.
>B) There's already a certain amount of
fuzziness around the IDispose pattern. with things like streams
exporting Close methods instead of Dispose methods.

Not usually "instead of" - "as well as". Close() is there for the sake
of familiarity with previous APIs, IMO.
>C) Some of the
other system patterns are used pretty loosely, like IEnumerable, with
its special casing for arrays, classes that implement GetEnumerator
but not IEnumerable, and iterators that don't implement Reset, &c.

That's certainly true.
>Besides, I think I can argue with a straight face that the tiny little
IDisposable class that one creates for all the examples above
constitute a sort of managed resource that needs to be freed - that
you are creating a resource that frees you from the need to explicitly
code your 'end' action.

You're clearly better able to maintain a straight face than I am :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Nov 27 '06 #6
Hi Cordell,

To address #3:

The C# using statement doesn't guarantee anything except that it will
compile to a try..finally block and call Dispose. The CLR doesn't guarantee
execution of the finally block unless it's part of a CER, so saying that the
C# using statement can be used to "guarantee" that the Dispose method is
called isn't entirely accurate. It serves only aesthetical purposes since a
try..finally block could easily be coded in its place, providing no
guarantees as well.

Regardless, I like that TransactionScope allows for use of the C# using
statement - it looks much nicer and reads better, IMO. Though,
semantically, it's wrong if you consider that it's actually calling
Dispose(), which is meant to free unmanaged resources. It's a shame there
isn't a different mechanism for calling a method in place of Dispose, such
as a "with" block that calls a "Complete" method on an "IScopedOperation"
interface - or something. Actually, that might be a bad idea :)

--
Dave Sexton

"Cordell Lawrence (News Group)" <co**************@hotmail.comwrote in
message news:OW****************@TK2MSFTNGP02.phx.gbl...
Guys, thank you for all the valuable input. Let me now add my two cents:

The official (and much bloged) documented purpose of IDisposable revolves
around the management of memory (unmanaged and disposable managed
instances) and advice on the proper use of the pattern and Finalizers.

Facts:
1. IDisposable.Dispose() is just a normal method, it has no special
meaning to the runtime
2. IDisposable.Dispose() must be called explicitly by the developer
3. The .NET 'using' syntax is a little more than a syntactic sugar
- It guarantees that the Dispose() method is called at the end of the
using scope
-*And! When using this construct the compiler ensures that the 'using
variables' cannot be modified either directly or indirectly
through passing it as out or ref parameters to other method anywhere
within the using scope

To me, these are all points for this pattern being used for more that
memory clean up, and this is evidenced by the implementation of for
example System.Transactions.TransactionScope. Most of the Dispose() method
of the TransactionScope type deals with maintaining State (on the
ThreadStatic variables that maintain info about the current Transaction
etc.)

Check out the following link where Stephen Toub uses the properties of
this pattern to implement his Scope<Ttype.
http://msdn.microsoft.com/msdnmag/is...s/default.aspx

I find it interesting that designers of both types chose the following:
using ( Scope<objectscope = new Scope<object>() )
{
// code that is sensitive to the scope
}
As opposed to:
Scope<objectscope = new Scope<object>();
scope.Begin();
// code that is sensitive to the scope
scope.End();

I mean beyond the syntactic brevity, it seems like it was a conscious
choice to use the dispose pattern in this way. I mean you could argue that
Transactions and the generic T in the scope may implement IDisposable and
so, in keeping with good design the designers decided use the dispose
pattern and will recursively call Dispose() on its disposable members, but
I find that hard to swallow.

As for the semantic confusion, I believe that this exists not because of
the Naming of the method and interface but its documentation and the
context in which this pattern is usually referred to.

Cordell Lawrence
Teleios Systems Ltd.
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
>Jon Shemitz <jo*@midnightbeach.comwrote:
>Put it this way: I might use it for convenience within an internal set
of classes, but if I were writing a library I wouldn't implement
IDisposable on something that wasn't in *some* way freeing a resource.

I do see your point, but I'm not really sure how valid it is, at least
in the context of C# and the `using` statement, where you don't
actually see a Dispose() call. (Languages like Delphi for .NET that
lack a `using` statement are a different story.)

If I write a library, it doesn't matter whether I write it in C# or not
- it could be used in a different language (eg Delphi.NET) which
*doesn't* have a using statement.
>>The way I see it, implementing IDispose in these cases just means that
you can use a `using` statement to make your code smaller and less
cluttered. I admit there is a certain amount of semantic violence, but
there are three reasons I don't think that matters, here. A) Semantic
violence matters where there's a possibility of confusion, which I
don't think is the case, here. I would, in fact, argue that the
smaller code is clearer.

Where it's present - but if you end up calling Dispose() explicitly
from other languages, surely that would cause confusion. That's why I
made my comment about the difference between using it effectively for
private use and exposing it as part of a public class.
>>B) There's already a certain amount of
fuzziness around the IDispose pattern. with things like streams
exporting Close methods instead of Dispose methods.

Not usually "instead of" - "as well as". Close() is there for the sake
of familiarity with previous APIs, IMO.
>>C) Some of the
other system patterns are used pretty loosely, like IEnumerable, with
its special casing for arrays, classes that implement GetEnumerator
but not IEnumerable, and iterators that don't implement Reset, &c.

That's certainly true.
>>Besides, I think I can argue with a straight face that the tiny little
IDisposable class that one creates for all the examples above
constitute a sort of managed resource that needs to be freed - that
you are creating a resource that frees you from the need to explicitly
code your 'end' action.

You're clearly better able to maintain a straight face than I am :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too


Nov 27 '06 #7
Just came in my mind reading yours interesting discussin.

Don't forget the dispose methods which are overloaded.

As I know the dispose from the Connection, which removes the
connectionstring in advance.

Cor

"Dave Sexton" <dave@jwa[remove.this]online.comschreef in bericht
news:Oc**************@TK2MSFTNGP03.phx.gbl...
Hi Cordell,

To address #3:

The C# using statement doesn't guarantee anything except that it will
compile to a try..finally block and call Dispose. The CLR doesn't
guarantee execution of the finally block unless it's part of a CER, so
saying that the C# using statement can be used to "guarantee" that the
Dispose method is called isn't entirely accurate. It serves only
aesthetical purposes since a try..finally block could easily be coded in
its place, providing no guarantees as well.

Regardless, I like that TransactionScope allows for use of the C# using
statement - it looks much nicer and reads better, IMO. Though,
semantically, it's wrong if you consider that it's actually calling
Dispose(), which is meant to free unmanaged resources. It's a shame there
isn't a different mechanism for calling a method in place of Dispose, such
as a "with" block that calls a "Complete" method on an "IScopedOperation"
interface - or something. Actually, that might be a bad idea :)

--
Dave Sexton

"Cordell Lawrence (News Group)" <co**************@hotmail.comwrote in
message news:OW****************@TK2MSFTNGP02.phx.gbl...
>Guys, thank you for all the valuable input. Let me now add my two cents:

The official (and much bloged) documented purpose of IDisposable revolves
around the management of memory (unmanaged and disposable managed
instances) and advice on the proper use of the pattern and Finalizers.

Facts:
1. IDisposable.Dispose() is just a normal method, it has no special
meaning to the runtime
2. IDisposable.Dispose() must be called explicitly by the developer
3. The .NET 'using' syntax is a little more than a syntactic sugar
- It guarantees that the Dispose() method is called at the end of the
using scope
-*And! When using this construct the compiler ensures that the 'using
variables' cannot be modified either directly or indirectly
through passing it as out or ref parameters to other method anywhere
within the using scope

To me, these are all points for this pattern being used for more that
memory clean up, and this is evidenced by the implementation of for
example System.Transactions.TransactionScope. Most of the Dispose()
method of the TransactionScope type deals with maintaining State (on the
ThreadStatic variables that maintain info about the current Transaction
etc.)

Check out the following link where Stephen Toub uses the properties of
this pattern to implement his Scope<Ttype.
http://msdn.microsoft.com/msdnmag/is...s/default.aspx

I find it interesting that designers of both types chose the following:
using ( Scope<objectscope = new Scope<object>() )
{
// code that is sensitive to the scope
}
As opposed to:
Scope<objectscope = new Scope<object>();
scope.Begin();
// code that is sensitive to the scope
scope.End();

I mean beyond the syntactic brevity, it seems like it was a conscious
choice to use the dispose pattern in this way. I mean you could argue
that Transactions and the generic T in the scope may implement
IDisposable and so, in keeping with good design the designers decided use
the dispose pattern and will recursively call Dispose() on its disposable
members, but I find that hard to swallow.

As for the semantic confusion, I believe that this exists not because of
the Naming of the method and interface but its documentation and the
context in which this pattern is usually referred to.

Cordell Lawrence
Teleios Systems Ltd.
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft. com...
>>Jon Shemitz <jo*@midnightbeach.comwrote:
Put it this way: I might use it for convenience within an internal
set
of classes, but if I were writing a library I wouldn't implement
IDisposable on something that wasn't in *some* way freeing a
resource.

I do see your point, but I'm not really sure how valid it is, at least
in the context of C# and the `using` statement, where you don't
actually see a Dispose() call. (Languages like Delphi for .NET that
lack a `using` statement are a different story.)

If I write a library, it doesn't matter whether I write it in C# or not
- it could be used in a different language (eg Delphi.NET) which
*doesn't* have a using statement.

The way I see it, implementing IDispose in these cases just means that
you can use a `using` statement to make your code smaller and less
cluttered. I admit there is a certain amount of semantic violence, but
there are three reasons I don't think that matters, here. A) Semantic
violence matters where there's a possibility of confusion, which I
don't think is the case, here. I would, in fact, argue that the
smaller code is clearer.

Where it's present - but if you end up calling Dispose() explicitly
from other languages, surely that would cause confusion. That's why I
made my comment about the difference between using it effectively for
private use and exposing it as part of a public class.

B) There's already a certain amount of
fuzziness around the IDispose pattern. with things like streams
exporting Close methods instead of Dispose methods.

Not usually "instead of" - "as well as". Close() is there for the sake
of familiarity with previous APIs, IMO.

C) Some of the
other system patterns are used pretty loosely, like IEnumerable, with
its special casing for arrays, classes that implement GetEnumerator
but not IEnumerable, and iterators that don't implement Reset, &c.

That's certainly true.

Besides, I think I can argue with a straight face that the tiny little
IDisposable class that one creates for all the examples above
constitute a sort of managed resource that needs to be freed - that
you are creating a resource that frees you from the need to explicitly
code your 'end' action.

You're clearly better able to maintain a straight face than I am :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too



Nov 27 '06 #8
Hey Dave,
The C# using statement doesn't guarantee anything except that it will
compile to a try..finally block and call Dispose. The CLR doesn't
guarantee execution of the finally block unless it's part of a CER, so
saying that the C# using statement can be used to "guarantee" that the
Dispose method is called isn't entirely accurate.
Absolutely correct, point taken. Thanks for pointing that out, though all
documentation ignores that Runtime induced errors will throw your lovely
'back-out' code blocks/assumed error handling out the window and I also
believe that the semantics (and documentation) encourage the thinking that
it's a guarantee; same with all try...finally blocks, but we know better :)
It serves only aesthetical purposes since a try..finally block could
easily be coded in its place, providing no guarantees as well.
Well, this is where my point about it being a bit more than a 'systactic
sugar'/aesthetic comes in. I say this really because of the compile time
check that 'using variables' arn't reassigned in any way ...

using(Scope<objectscope = new Scope<object>() )
{
scope = new Scope<System.String>(); // Compile time error
CreateInstance(ref scope); // Compile time error
CreateInstanceEx(out scope); // Compile time error
// other code ...
}
as opposed to actually writing what the compiler will expand the using block
to:

Scope<objectscope;
try
{
Scope<objectscope = new Scope<object>(); // Original creation
code - using ( ... )

scope = new Scope<System.String>(); // Fine
CreateInstance(ref scope); // Fine
CreateInstanceEx(out scope); // Fine
}
finally
{
((IDisposable)scope).Dispose();
}
Regardless, I like that TransactionScope allows for use of the C# using
statement - it looks much nicer and reads better, IMO.
Lol ... people really like this point huh :), but that IMO, is really a
(*very valuable*) side effect rather than a core design requirement.
Though, semantically, it's wrong if you consider that it's actually
calling Dispose(), which is meant to free unmanaged resources. It's a
shame there isn't a different mechanism for calling a method in place of
Dispose, such as a "with" block that calls a "Complete" method on an
"IScopedOperation" interface - or something. Actually, that might be a
bad idea :)
Well, I guess that's the core of the argument ... that even though
IDisposable is just a regular interface and the Dispose method must be
called explicitly by the developer, the C# lexicon includes syntax that will
automatically call this method for us at the end of a code block. Question
is then, is it "right" or "worng" to expliot this for uses other than the
intended (semantic) use of the method. Humm, Food for though.

Ok final words, here's my thing: Finalizers are the only cleanup methods
formally acknowledged by the Runtime. This concept is necessary and often
abused by developers who are accustomed to pairing cleanup code with object
lifetime as in the days of C++, but it is not deterministic since it is
called asynchronously by the Runtime itself which resluts in holding on to
scarce resources longer than we would like or longer than is acceptable for
performance reasons. So we are provided with a standard formalized idiom,
"The Dispose Pattern" in which we can call in a deterministic fasion to free
unmanaged resources (the only thing that we can *deterministically* reclaim,
GC Handles the rest). So the Dispose method is sort of like an adopted
cousin Harry... twice removed, that we have around to clean up shop when
we're in a hurry because the multitasking maid thats overworked can't do
stuff the moment we asked her to :) But why not use Harry to cook as well?
.... maybe a robot would be a better example, but what the heck thats enough
from me.

Guys, I really appreciate the points raised in this discussion.

Cordell Lawrence
Teleios Systems Ltd.

"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:Oc**************@TK2MSFTNGP03.phx.gbl...
Hi Cordell,

To address #3:

The C# using statement doesn't guarantee anything except that it will
compile to a try..finally block and call Dispose. The CLR doesn't
guarantee execution of the finally block unless it's part of a CER, so
saying that the C# using statement can be used to "guarantee" that the
Dispose method is called isn't entirely accurate. It serves only
aesthetical purposes since a try..finally block could easily be coded in
its place, providing no guarantees as well.

Regardless, I like that TransactionScope allows for use of the C# using
statement - it looks much nicer and reads better, IMO. Though,
semantically, it's wrong if you consider that it's actually calling
Dispose(), which is meant to free unmanaged resources. It's a shame there
isn't a different mechanism for calling a method in place of Dispose, such
as a "with" block that calls a "Complete" method on an "IScopedOperation"
interface - or something. Actually, that might be a bad idea :)

--
Dave Sexton

"Cordell Lawrence (News Group)" <co**************@hotmail.comwrote in
message news:OW****************@TK2MSFTNGP02.phx.gbl...
>Guys, thank you for all the valuable input. Let me now add my two cents:

The official (and much bloged) documented purpose of IDisposable revolves
around the management of memory (unmanaged and disposable managed
instances) and advice on the proper use of the pattern and Finalizers.

Facts:
1. IDisposable.Dispose() is just a normal method, it has no special
meaning to the runtime
2. IDisposable.Dispose() must be called explicitly by the developer
3. The .NET 'using' syntax is a little more than a syntactic sugar
- It guarantees that the Dispose() method is called at the end of the
using scope
-*And! When using this construct the compiler ensures that the 'using
variables' cannot be modified either directly or indirectly
through passing it as out or ref parameters to other method anywhere
within the using scope

To me, these are all points for this pattern being used for more that
memory clean up, and this is evidenced by the implementation of for
example System.Transactions.TransactionScope. Most of the Dispose()
method of the TransactionScope type deals with maintaining State (on the
ThreadStatic variables that maintain info about the current Transaction
etc.)

Check out the following link where Stephen Toub uses the properties of
this pattern to implement his Scope<Ttype.
http://msdn.microsoft.com/msdnmag/is...s/default.aspx

I find it interesting that designers of both types chose the following:
using ( Scope<objectscope = new Scope<object>() )
{
// code that is sensitive to the scope
}
As opposed to:
Scope<objectscope = new Scope<object>();
scope.Begin();
// code that is sensitive to the scope
scope.End();

I mean beyond the syntactic brevity, it seems like it was a conscious
choice to use the dispose pattern in this way. I mean you could argue
that Transactions and the generic T in the scope may implement
IDisposable and so, in keeping with good design the designers decided use
the dispose pattern and will recursively call Dispose() on its disposable
members, but I find that hard to swallow.

As for the semantic confusion, I believe that this exists not because of
the Naming of the method and interface but its documentation and the
context in which this pattern is usually referred to.

Cordell Lawrence
Teleios Systems Ltd.
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft. com...
>>Jon Shemitz <jo*@midnightbeach.comwrote:
Put it this way: I might use it for convenience within an internal
set
of classes, but if I were writing a library I wouldn't implement
IDisposable on something that wasn't in *some* way freeing a
resource.

I do see your point, but I'm not really sure how valid it is, at least
in the context of C# and the `using` statement, where you don't
actually see a Dispose() call. (Languages like Delphi for .NET that
lack a `using` statement are a different story.)

If I write a library, it doesn't matter whether I write it in C# or not
- it could be used in a different language (eg Delphi.NET) which
*doesn't* have a using statement.

The way I see it, implementing IDispose in these cases just means that
you can use a `using` statement to make your code smaller and less
cluttered. I admit there is a certain amount of semantic violence, but
there are three reasons I don't think that matters, here. A) Semantic
violence matters where there's a possibility of confusion, which I
don't think is the case, here. I would, in fact, argue that the
smaller code is clearer.

Where it's present - but if you end up calling Dispose() explicitly
from other languages, surely that would cause confusion. That's why I
made my comment about the difference between using it effectively for
private use and exposing it as part of a public class.

B) There's already a certain amount of
fuzziness around the IDispose pattern. with things like streams
exporting Close methods instead of Dispose methods.

Not usually "instead of" - "as well as". Close() is there for the sake
of familiarity with previous APIs, IMO.

C) Some of the
other system patterns are used pretty loosely, like IEnumerable, with
its special casing for arrays, classes that implement GetEnumerator
but not IEnumerable, and iterators that don't implement Reset, &c.

That's certainly true.

Besides, I think I can argue with a straight face that the tiny little
IDisposable class that one creates for all the examples above
constitute a sort of managed resource that needs to be freed - that
you are creating a resource that frees you from the need to explicitly
code your 'end' action.

You're clearly better able to maintain a straight face than I am :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Nov 27 '06 #9
Cordell,

Here's another angle on the subject you can consider. The 'foreach'
construct will call Dispose on the enumerator if it implements the
IDisposable interface. So, 'using' is not the keyword in C# that will
invoke Dispose. I'm not really trying to make a point of this fact
here. I just thought it's interesting in the general context of this
thread.

Brian

Nov 27 '06 #10
Hi Cordell,

<snip>
>It serves only aesthetical purposes since a try..finally block could
easily be coded in its place, providing no guarantees as well.

Well, this is where my point about it being a bit more than a 'systactic
sugar'/aesthetic comes in. I say this really because of the compile time
check that 'using variables' arn't reassigned in any way ...
That's a good point. There is some consequential value to using the "using"
statement: protection against reassignment.

<snip>
>Regardless, I like that TransactionScope allows for use of the C# using
statement - it looks much nicer and reads better, IMO.

Lol ... people really like this point huh :), but that IMO, is really a
(*very valuable*) side effect rather than a core design requirement.
It's important to me that a language's constructs are legible (but not
overly verbose as in VB.NET, IMO). I believe legibility is a core design
requirement for the authors of C#. It seems that way just from reading some
of their blogs. After all, it's not like C# is the CLR - it's a "language"
compiler :)

<snip>

And I just wanted to toss in another wrench: TransactionScope isn't such a
good example anyway because it may use Dispose to free distributed
transactional resources. So our use of the C# using statement is actually
appropriate here :)

Other, actually nonconforming uses for the C# using statement may have been
submitted in this thread but I can't think of any that I use that don't have
something unmanaged to be disposed of. Any suggestions?

--
Dave Sexton
Nov 27 '06 #11
Sorry I took so long to reply to you on this one Dave,

I mean, I've just about written a research paper on this now that I've gone
through everything that I've written here and to my collegue as well as
things that I've just written for my own clarity. I just wanted to address
you final wrench in the works:
And I just wanted to toss in another wrench: TransactionScope isn't such
a good example anyway because it may use Dispose to free distributed
transactional resources. So our use of the C# using statement is actually
appropriate here :)
Well, from actually reflecting on the Dispose method of the TransactionScope
BCL Type even before I chose it as an example, I found that much more than
the lion's share of this method has *nothing* to do with Disposing of
resources. In fact this class does not itself hold on to unmanaged
resources. IDisposable documentation does state that if a type has members
that implement this interface, then the type should implement the interface
as well which should dispose of all its disposable members. That may very
well apply here. The System.Transactions.TransactionScope type has as
members that implement IDisposable, most notably the transaction that it may
have created, but if you look at the *implementation* of the method, clearly
this type's designers had alot more in mind than Disposing of its
Transaction members.

This is what I was trying to get at in my response to my collegue and my
first post:

"Instances of System.Transactions.Transaction types may be elevated from LTM
transactions to Enterprise Services DTC Transactions that utilize unmanaged
resources that may need to be reclaimed. Quite apart from this fact though,
the implementation of the TransactionScope type and it's affinity to and
reliance on the dispose pattern for the proper execution of its core
function, unrelated to unmanaged resources or the deterministic reclamation
of those resources most clearly illustrates my point that the Dispose
Pattern's usefulness can exceed memory management."

I would have liked to hear fom the developer that worked on this type why he
chose to use the Dispose method to implement so much of this type's clean up
logic, if the documentation of IDisposable says (paraphrase) that this
method should be used for freeing resources. I guess one could argue that
all the clean up done before the Transaction(s) are Disposed are par for the
course which will eventually lead to the cleanup but thats beginning to blur
the lines no?

Cordell Lawrence
Teleios Systems Ltd.

"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:OP**************@TK2MSFTNGP03.phx.gbl...
Hi Cordell,

<snip>
>>It serves only aesthetical purposes since a try..finally block could
easily be coded in its place, providing no guarantees as well.

Well, this is where my point about it being a bit more than a 'systactic
sugar'/aesthetic comes in. I say this really because of the compile time
check that 'using variables' arn't reassigned in any way ...

That's a good point. There is some consequential value to using the
"using" statement: protection against reassignment.

<snip>
>>Regardless, I like that TransactionScope allows for use of the C# using
statement - it looks much nicer and reads better, IMO.

Lol ... people really like this point huh :), but that IMO, is really a
(*very valuable*) side effect rather than a core design requirement.

It's important to me that a language's constructs are legible (but not
overly verbose as in VB.NET, IMO). I believe legibility is a core design
requirement for the authors of C#. It seems that way just from reading
some of their blogs. After all, it's not like C# is the CLR - it's a
"language" compiler :)

<snip>

And I just wanted to toss in another wrench: TransactionScope isn't such
a good example anyway because it may use Dispose to free distributed
transactional resources. So our use of the C# using statement is actually
appropriate here :)

Other, actually nonconforming uses for the C# using statement may have
been submitted in this thread but I can't think of any that I use that
don't have something unmanaged to be disposed of. Any suggestions?

--
Dave Sexton


Dec 3 '06 #12
Hi Cordell,

Interesting, but I assumed that much about TransactionScope. I was just
suggesting that I'm unaware of any type that uses the Dispose pattern to
only manage lifetime, but not unmanaged resources.

As for lines being blurred, I'd say they certainly are, but it doesn't
matter when the disposal pattern is being used for its recommended purpose
as well. In other words, even if TransactionScope didn't manage the scope
using the Dispose pattern, you'd want to use it anyway because of the
possibility of unmanaged resources being used. So, in a way, the design
wasn't against the standard, it was supplementing it.

Personally, I don't think I'm against using the "using" statement to manage
the lifetime of an object that has no unmanaged resources to be disposed of,
directly or indirectly.

For one thing, the semantics behind lifetime management and the Dispose
pattern correspond almost perfectly. The only difference that I see is that
normally, disposed objects should no longer be valid, however when managing
the lifetime of an object it might make sense to leave certain aspects of
the object accessible even after disposal. Also, how many developers that
you know actually code ObjectDisposedException into their public properties
and methods anyway?

--
Dave Sexton

"Cordell Lawrence (News Group)" <co**************@hotmail.comwrote in
message news:ek**************@TK2MSFTNGP04.phx.gbl...
Sorry I took so long to reply to you on this one Dave,

I mean, I've just about written a research paper on this now that I've
gone through everything that I've written here and to my collegue as well
as things that I've just written for my own clarity. I just wanted to
address you final wrench in the works:
>And I just wanted to toss in another wrench: TransactionScope isn't such
a good example anyway because it may use Dispose to free distributed
transactional resources. So our use of the C# using statement is
actually appropriate here :)

Well, from actually reflecting on the Dispose method of the
TransactionScope BCL Type even before I chose it as an example, I found
that much more than the lion's share of this method has *nothing* to do
with Disposing of resources. In fact this class does not itself hold on to
unmanaged resources. IDisposable documentation does state that if a type
has members that implement this interface, then the type should implement
the interface as well which should dispose of all its disposable members.
That may very well apply here. The System.Transactions.TransactionScope
type has as members that implement IDisposable, most notably the
transaction that it may have created, but if you look at the
*implementation* of the method, clearly this type's designers had alot
more in mind than Disposing of its Transaction members.

This is what I was trying to get at in my response to my collegue and my
first post:

"Instances of System.Transactions.Transaction types may be elevated from
LTM
transactions to Enterprise Services DTC Transactions that utilize
unmanaged
resources that may need to be reclaimed. Quite apart from this fact
though,
the implementation of the TransactionScope type and it's affinity to and
reliance on the dispose pattern for the proper execution of its core
function, unrelated to unmanaged resources or the deterministic
reclamation
of those resources most clearly illustrates my point that the Dispose
Pattern's usefulness can exceed memory management."

I would have liked to hear fom the developer that worked on this type why
he chose to use the Dispose method to implement so much of this type's
clean up logic, if the documentation of IDisposable says (paraphrase) that
this method should be used for freeing resources. I guess one could argue
that all the clean up done before the Transaction(s) are Disposed are par
for the course which will eventually lead to the cleanup but thats
beginning to blur the lines no?

Cordell Lawrence
Teleios Systems Ltd.

"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:OP**************@TK2MSFTNGP03.phx.gbl...
>Hi Cordell,

<snip>
>>>It serves only aesthetical purposes since a try..finally block could
easily be coded in its place, providing no guarantees as well.

Well, this is where my point about it being a bit more than a 'systactic
sugar'/aesthetic comes in. I say this really because of the compile time
check that 'using variables' arn't reassigned in any way ...

That's a good point. There is some consequential value to using the
"using" statement: protection against reassignment.

<snip>
>>>Regardless, I like that TransactionScope allows for use of the C# using
statement - it looks much nicer and reads better, IMO.

Lol ... people really like this point huh :), but that IMO, is really a
(*very valuable*) side effect rather than a core design requirement.

It's important to me that a language's constructs are legible (but not
overly verbose as in VB.NET, IMO). I believe legibility is a core design
requirement for the authors of C#. It seems that way just from reading
some of their blogs. After all, it's not like C# is the CLR - it's a
"language" compiler :)

<snip>

And I just wanted to toss in another wrench: TransactionScope isn't such
a good example anyway because it may use Dispose to free distributed
transactional resources. So our use of the C# using statement is
actually appropriate here :)

Other, actually nonconforming uses for the C# using statement may have
been submitted in this thread but I can't think of any that I use that
don't have something unmanaged to be disposed of. Any suggestions?

--
Dave Sexton



Dec 4 '06 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

26
by: codymanix | last post by:
Last night I had several thought about RAII and want to discuss a bit. Why doesn't CSharp support destructors in structs? Wouldn't that make RAII possible like in C++? When the struct goes out of...
24
by: Jazper | last post by:
hi i have this problem. i made a class deverted by CRootItem with implementation of IDisposable-Interface. i made a test-funktion to test my Dispose-Method.... but when set a breakpoint in my...
2
by: Brian Henry | last post by:
when you make a class implement IDisposable, is that basicly the same thing as a destructor implementation in C++? it seems ot just add a dispose method to a class, which in C++ that'd be a...
4
by: Helge Jensen | last post by:
In C# 2.0 System.IO.Stream is declared as: public class Stream: ..., IDisposable { ... public void Dispose(); public void Dispose(bool); IDisposable.Dispose(); } Which must be a...
4
by: phl | last post by:
hi, My question is: 1. To avoid possible memory leaks, when you use this pattern, after you have dealth with the unmanaged resources and before you take your object off the finalize queue,...
47
by: Hilton | last post by:
Hi, I'm sure I'm simplifying things here, but how about if the GC did this to objects that implement IDisposable: 1. Always Generation 1 (I think that is the correct name) 2. Get aggressive...
1
by: =?Utf-8?B?c3VydHVyeg==?= | last post by:
Hi, I'm using VB2005 + Office XP Enterprise. If you create a Word.Application object, you risk a memory leak if your application crashes because Word.Application is an unmanaged COM Interop...
34
by: Creativ | last post by:
Why does Thread class not support IDisposable? It's creating quite some problem. Namely, it can exhaust the resource and you have not control over it.
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.