On Fri, 25 Jul 2008 09:35:20 -0700, Andre Kaufmann
<an************ *********@t-online.dewrote:
Peter Duniho wrote:
>On Thu, 24 Jul 2008 22:43:52 -0700, Andre Kaufmann
<an*********** **********@t-online.dewrote:
[...]
>>I can include reference counting, but I can't use smart pointers.
Why not?
Not in that way as they are used in C++.
E.g. if I assign one smart pointer to another in C++ the reference is
incremented. In C# I would have to use a method for the assignment.
But I can't prevent one smart pointer accidentally be assigned to
another one in C#.
So I don't see that much value in smart pointers in C#, I then rather
would prefer the AddRef method directly and not using a smart pointer.
Ah, I see. So it's not that you can't do it. You just don't want to do
it the way you'd need to in C#.
You're right, assignment operator overload isn't available in C#. But
such an overloaded operator's really just another method. There's no
functional difference between simply implementing it as an explicit
method. In fact, some will argue that there's a good reason to not allow
overloading of the assignment operator and that making that sort of thing
explicit is a _good_ "don't blow your leg off" sort of thing. :)
For example in the following architecture:
A simple shared buffer holding memory and resources: [b]
[b] -Thread #1
[b] ---[ReceiverThread] - passes --[b] -Thread #2
[b] -Thread #3
The buffer is passed to multiple receivers which "do something" with the
buffer. After the last thread has finished it's operations it should
release the buffer and store it into a central pool for reusing and
should additionally release eventually used resources immediately.
How do I know if the last thread has finished ?
There are any number of approaches you can take. But if you really like
ref-counting, then the solution is to just ref-count the object. I don't
know what the phrase "eventually used resources" means, but if you're
pooling the object I don't see why you'd release its resources.
Conversely, if you're releasing its resources, then just get rid of the
object and be done with it.
In either case, you may still want _some_ form of ref-counting, either
managed by the pool manager itself, or as part of the object. But either
way, it's much ado about nothing.
[...]
A structure is a value type in C# and therefore copied on assignment and
immediately "freed" if the control block is left.
If I could add an destructor and overload the assignment operator I
would have a possibility to implement smart pointers like in C++.
IDisposable can replace the functionality of the destructor (in
conjunction with the "using" statement), and yes you'd have to have an
explicit method instead of an overloaded assignment operator. I don't
find those differences to be material.
>>But currently in C# you have to either use a temporary object in
combination with using or call the AddRef / Release functions by hand.
How is a smart pointer not a temporary object?
Yes, that's the point. I know how to handle it temporarily in a control
block, but when the smart pointer is added to a list of smart pointers
and removed from the list I have no possibility to "force" the automatic
release of the reference.
I have to remove the smart pointer from the list and then manually call
release. What's the point of a smart pointer in this case ? I could
rather use the reference counted object directly
When the smart pointer is not stack-allocated, don't you have to manually
delete the smart pointer in C++? What's the difference?
[...]
I only have the feeling that just creating a new object to automatically
call methods of another object in the Dispose method is somewhat
overkill.
Well, certainly there is the question of just how important smart pointers
are. Personally, I find them superfluous. You can still get ref-counting
bugs even if you're using smart pointers, if you use them incorrectly.
But inasmuch as there's some benefit to wrapping ref-counting in a
clearer, more automatic API, that benefit is available in C#, just using
slightly different syntax.
The GC is fast, but why should I add pressure to it, by permanently
allocating temporary objects ?
The phrase "permanentl y allocating temporary objects" doesn't make sense
to me. But regardless, the last thing you really need to worry about is
pressuring the GC. Assuming you're using a reference type for your smart
pointer (which may or may not be true anyway), the GC can handle the load
just fine.
I agree It's no big deal if the temporary object is created rarely or
held for a long time.
Au contraire. One of the GC's strengths is its ability to deal with large
numbers of frequently allocated, short-lived objects.
But additionally a smart pointer should behave like another ordinary
pointer, with additional functionality that is under my control.
To some extent, the real issue here is that there's a fundamental paradigm
shift that needs to be made. If you don't want to make that shift, that's
fine. But that's not an indictment of C#. The whole concept of "smart
pointer" is related to the needs of unmanaged code (and especially COM).
An application written to the strengths of C# and the .NET Framework will
most often never run into ref-counting issues at all, and if and when it
does happen, there are viable work-arounds.
Again: much ado about nothing.
Pete