By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,389 Members | 1,955 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,389 IT Pros & Developers. It's quick & easy.

Swap function

P: n/a
Does anyone know if an analogue to the "swap()" function found in C++ exists
in C#. For those not familiar, let's say you have a function that loads some
collection passed in by reference. If an error occurs while loading then the
collection will be in an indeterminate state. The work-around in C++ is to
load a temporary collection first and once successful, invoke a (native)
"swap()" function to exchange each object's internal "handle" to the
collection (fast, efficient, and error-free). Before I start rolling my own,
does anything like this already exist (natively) in C# (or what's the
generally accepted equivalent if any). Thanks.
Jan 15 '07 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Hi

No, AFAIK there is nothing like that in .NET, could you be a little more
explanative regarding what you are loading, etc?
As I said this is the first time ever that I see mentioned something like
this.
--
Ignacio Machin
machin AT laceupsolutions com
"Jack White" <no_spam@_nospam.comwrote in message
news:%2****************@TK2MSFTNGP02.phx.gbl...
| Does anyone know if an analogue to the "swap()" function found in C++
exists
| in C#. For those not familiar, let's say you have a function that loads
some
| collection passed in by reference. If an error occurs while loading then
the
| collection will be in an indeterminate state. The work-around in C++ is to
| load a temporary collection first and once successful, invoke a (native)
| "swap()" function to exchange each object's internal "handle" to the
| collection (fast, efficient, and error-free). Before I start rolling my
own,
| does anything like this already exist (natively) in C# (or what's the
| generally accepted equivalent if any). Thanks.
|
|
Jan 15 '07 #2

P: n/a
Jack White wrote:
Does anyone know if an analogue to the "swap()" function found in C++ exists
in C#. For those not familiar, let's say you have a function that loads some
collection passed in by reference. If an error occurs while loading then the
collection will be in an indeterminate state. The work-around in C++ is to
load a temporary collection first and once successful, invoke a (native)
"swap()" function to exchange each object's internal "handle" to the
collection (fast, efficient, and error-free). Before I start rolling my own,
does anything like this already exist (natively) in C# (or what's the
generally accepted equivalent if any). Thanks.
If you pass the argument by ref you can do that in C#.

Arne
Jan 15 '07 #3

P: n/a
No, AFAIK there is nothing like that in .NET, could you be a little more
explanative regarding what you are loading, etc?
For the moment I'm just wondering about the situation in general. How would
you handle the example I cited for instance. The C++ standard documents
exception safety rules which aren't as much of an issue in C# but still
present to some extent. There are three fundamental rules known as the
"basic", "strong" and "nothrow" guarantees which is what I'm really asking
about. You can read about these on the web (or see here for Stroustrup's own
treatise on the subject: http://www.research.att.com/~bs/3rd_safe.pdf) but
I'm really interested in how C# deals with these issues. Any insight you can
provide would be welcome. Thanks.
Jan 15 '07 #4

P: n/a
Jack White wrote:
Does anyone know if an analogue to the "swap()" function found in C++ exists
in C#. For those not familiar, let's say you have a function that loads some
collection passed in by reference. If an error occurs while loading then the
collection will be in an indeterminate state. The work-around in C++ is to
load a temporary collection first and once successful, invoke a (native)
"swap()" function to exchange each object's internal "handle" to the
collection (fast, efficient, and error-free). Before I start rolling my own,
does anything like this already exist (natively) in C# (or what's the
generally accepted equivalent if any). Thanks.
In C++ this is required due to risks of exceptions in copy constructors,
no? AFAIK it's down to exception safety in value-oriented types. It's
especially pernicious because of STL value-oriented containers, and the
risks of exceptions while adding value-types with copy constructors,
assignment operators etc.

The normal practice in C# would be to either (1) return a new collection
rather than filling a passed-in collection (this is the far more common
method), or (2) undo changes in an except block. E.g.:

---8<---
void FillInStuff<T>(List<Tstuff)
{
List<Tsaved = new List<T>(stuff);
try
{
// risky operation
}
except
{
stuff.Clear();
stuff.AddRange(saved);
throw; // rethrow exception
}
}
--->8---
-- Barry

--
http://barrkel.blogspot.com/
Jan 16 '07 #5

P: n/a
In C++ this is required due to risks of exceptions in copy constructors,
no?
Copy constructors are only one aspect of it.
AFAIK it's down to exception safety in value-oriented types.
It's especially pernicious because of STL value-oriented containers, and
the
risks of exceptions while adding value-types with copy constructors,
assignment operators etc.

The normal practice in C# would be to either (1) return a new collection
rather than filling a passed-in collection (this is the far more common
method), or (2) undo changes in an except block. E.g.:

---8<---
void FillInStuff<T>(List<Tstuff)
{
List<Tsaved = new List<T>(stuff);
try
{
// risky operation
}
except
{
stuff.Clear();
stuff.AddRange(saved);
throw; // rethrow exception
}
}
The issues run much deeper. First, what exception guarantees do the native
..NET types make, let alone user-defined types (also considering their impact
on exception safety when interacting with the native .NET types). Can I
safely assume for instance that anytime I call a member function on any
native .NET object, my object will remain completely unaltered if an
exception is thrown (the "strong guarantee")? Or does it only support the
"basic guarantee" for instance, where the object's invariants are maintained
so I can recover (the object isn't corrupted), but the state of the object
is otherwise unknown (maybe I only have to reset the cursor in some stream
object for instance). Your own example provides a simple demonstration of
this situation. First, it's inefficient. You construct a backup copy first
when it would be much faster to simply build your new copy as a temporary
and reassign it to the original in an exception-safe way (normally by
exchanging the references but that requires passing it in by reference -
note that C++ can do it this way as well or otherwise rely on a "swap()"
function which simply and safely exchanges each object's internal "handle"
to the data). Even rolling it back requires yet more copying . What if
failure occurs however at any given time during the call to "Clear()" or
"AddRange()". What is the state of "stuff" at this point. Well, it's already
lost its existing data in the "try" block itself (a no-no) but more to the
point, what if "AddRange()" throws for example. Is "stuff" even in a valid
(uncorrupted) state. I assume the C# language says yes (providing the "basic
guarantee") but even so, is "stuff" itself now partially-filled with data or
does it remain completely intact (clear because of your previous call but
even without clearing it first, what's the state of data you copied into it
in the "try" block). Moreover, rolling back changes after an error may not
always be practical, efficient, possible, or exception safe itself. The C++
committee spent years hashing these issues out and C# probably adopted many
of their decisions but I'd like to see some white-paper on the subject in
the context of C# itself (whose issues aren't as complex as C++ but exist
nevertheless).
Jan 17 '07 #6

P: n/a
Jack White wrote:
The issues run much deeper.
Yes, I'm well aware of some of the hair-splitting debates on this in the
C++ community. I still stand by my position though, that the worst of it
is caused by the ability of the user to inject exceptions into
operations that could never throw in a language like C#, such as
assignments, parameter passing, return values, etc.

Simple example: it's impossible to write an exception-safe mutator
template method that returns a value of a user-defined type in C++, as
you know. std::stack<T>::pop() doesn't return the value popped for
precisely this reason.
First, what exception guarantees do the native
.NET types make
You'll need to read the documentation to get this, but usually time with
..NET Reflector is needed to get full information. Note that out of
memory and stack overflow can occur at almost any time, and will result
in the app domain being torn down. This puts a hard limit on how
resilient an individual app domain can be, so you may want (need) to
lower your ambitions in this area.
Can I
safely assume for instance that anytime I call a member function on any
native .NET object, my object will remain completely unaltered if an
exception is thrown (the "strong guarantee")? Or does it only support the
"basic guarantee" for instance, where the object's invariants are maintained
so I can recover (the object isn't corrupted), but the state of the object
is otherwise unknown (maybe I only have to reset the cursor in some stream
object for instance).
This isn't a scientific statement, but a well-written class ought to
hold the strong guarantee for unitary operations (e.g. List<T>.Add), and
hold the basic guarantee for aggregate operations (e.g.
List<T>.AddRange) (but note below that it doesn't). One hopes that the
..NET classes in question are well written, and mostly they are. There
are some dodgy ones in there too, unfortunately (though most of the
crimes are in API design, not implementation).
Your own example provides a simple demonstration of
this situation. First, it's inefficient.
Efficiency is more important than correctness? If your concern is about
strong exception safety, I'd relegate efficiency to the bottom of your
list, because strong exception safety usually implies transactions,
which are (almost) never free.
You construct a backup copy first
when it would be much faster to simply build your new copy as a temporary
and reassign it to the original in an exception-safe way (normally by
exchanging the references but that requires passing it in by reference -
note that C++ can do it this way as well
C# can do this also, via 'ref', which passes in the reference to the
list by reference rather than by value. However, this is rare because it
forces the caller to control all the existing references to that list
instance on the heap and update them with the new reference value it
receives from calling the method. That's why I didn't write the method
that way.
or otherwise rely on a "swap()"
function which simply and safely exchanges each object's internal "handle"
to the data).
If you want to do this, you can't use the .NET collection classes.
You're free to write your own classes to do this of course.
Even rolling it back requires yet more copying .
Yep. Strong exception safety for aggregate operations basically amounts
to starting a transaction and rolling it back. The 'copy the world, copy
back if error' is one of the shortest (in code space) ways of doing
that, which is all I was after (also, not knowing what was happening in
the body of the try..except).
What if
failure occurs however at any given time during the call to "Clear()"
The List<T>.Clear() operation won't fail, but you'll have to take my
word for that! It clears the internal array, and sets an index, but it
doesn't do anything that would throw an exception (except stack
overflow, which you can't do much about, as indicated earlier).
or
"AddRange()".
AddRange() could throw OutOfMemoryException or StackOverflow when
creating the iterator, but again, you can't control that. If one were
passing an arbitrary collection to AddRange(), and threw an exception in
ICollection<T>.CopyTo(), then one could really mess up the list (so
List<T>.AddRange() provides neither exception guarantee). That won't
happen with List<T>.CopyTo() though, because it boils down to
Array.Copy, which shouldn't have any problems (though it specifically
doesn't give guarantees, i.e. it may corrupt the array if it e.g. can't
cast an instance when copying from one array to another).
What is the state of "stuff" at this point.
It's pretty irrelevant, since the application is terminating if either
of the above two exceptions are thrown.
Well, it's already
lost its existing data in the "try" block itself (a no-no)
I don't understand what you mean by this. "stuff" is restored by the
except block, and the only things that can stop that are fatal errors,
due to generics being used in the example (so e.g. Array.Copy can't fail
due to typecasting etc.).
but more to the
point, what if "AddRange()" throws for example. Is "stuff" even in a valid
(uncorrupted) state.
In the most general sense, for any AddRange() call, no, it may be
corrupted.
I assume the C# language
The C# language doesn't much to say in this specific matter. It's down
to how the .NET library classes themselves are written, which is more
part of the CLI specification than C#.
says yes (providing the "basic
guarantee") but even so, is "stuff" itself now partially-filled with data or
does it remain completely intact
No, data may be shifted up, items may be lost, etc.
(clear because of your previous call but
even without clearing it first, what's the state of data you copied into it
in the "try" block).
Exception safety is a recursive concept; the try block in my example is
empty, but of course for the whole thing to be exception safe, the
operations inside must also be exception safe, possibly requiring extra
exception handlers etc.
Moreover, rolling back changes after an error may not
always be practical, efficient, possible,
It always amuses me when C++ programmers put "efficient" ahead of things
like correctness, or even "possible" ;-)
or exception safe itself.
Of course; that's why basic exception guarantees are more usual for
aggregate operations.
The C++
committee spent years hashing these issues out
And I stand by what I said at the start. Another reason why it's so bad
in C++ is lack of GC and stronger guarantees on e.g. bounds-checked
arrays. Exception safety is usually required to ensure that all memory
is freed up, and to avoid writing past the ends of arrays, etc.
and C# probably adopted many
of their decisions
Largely, no, not in this area, I don't think so.
but I'd like to see some white-paper on the subject in
the context of C# itself (whose issues aren't as complex as C++ but exist
nevertheless).
I think that would be good too, beyond what's covered by the reliability
contract and constrained execution region stuff. The approach in .NET is
much more a "best-effort" setup, yet bounded by the app domain, rather
than giving hard guarantees on the framework classes.

-- Barry

--
http://barrkel.blogspot.com/
Jan 19 '07 #7

This discussion thread is closed

Replies have been disabled for this discussion.