J
jehugaleahsa
Hello:
As an avid reader of C++ books, I know a lot of programmers out there
are confronted with the challenge of exception safety.
For those who don't know what it is, it is writing code in such a way
that an exception will not cause a class to be left in an unstable
state. For instance, you wouldn't want an OutOfMemoryException leaving
a container with an invalid size or missing elements.
Now, in C++, the main idea is to write code so that you do as much
work as possible withouth doing anything that can cause and exception,
and back track if something does go wrong. In C++, implementors
usually do this by using an idiom called, copy/modify/swap, to achieve
exception safety.
I am wondering if this is easier to do in C#. Assignment in C# has a
different meaning than assignment in C++ for reference types.
Assignment makes things equal, not equivelent. C# natively supports
Clone(), but not really a copy ctor. Since C# uses references, I can't
really change my reference since multiple references may be pointed to
the object I am modifying (some times).
Imagine there is a class that looks something like this:
class Dog
{
private int age = 0;
// . . .
public void CelebrateBirthday()
{
++age;
// . . . something throws an exception at this point
}
}
If I were to execute this code and an exception was thrown, my dog
would be a year older than he really should be (assuming that I want
to rollback (undo) the change in the face of an exception). One
solution would look like this:
public void CelebrateBirthday()
{
try
{
++age;
// . . . something throws an exception at this point
}
catch
{
--age;
// undo potential changes to other fields (may require storing
the old value)
}
}
Now, I would have to write that around every mutating method/property
in my class. YUCK! In a class with dozens of fields, that would be a
nightmare.
This is my proposed solution, similar to how it is done is C++:
private void copy(Dog dog)
{
age = dog.age;
// transfer additional fields
}
public void CelebrateBirthday()
{
Dog tempDog = new Dog();
tempDog.copy(this);
++tempDog.age;
// . . . something throws an exception at this point
this.copy(tempDog);
}
Notice that there is no longer a need for try/catch. If something goes
wrong, the copy, tempDog, just gets wasted. The final line is to
update 'this' with the changes.
Now, this seems really simple to me. I have trouble believing that
someone didn't come up with something more general or correct (I think
mine is correct???). For instance, there is a lot to be concerned
about with deep/shallow copies.
Community-wide approaches are what I am looking for. Anyone?
Thanks,
Travis Parks
As an avid reader of C++ books, I know a lot of programmers out there
are confronted with the challenge of exception safety.
For those who don't know what it is, it is writing code in such a way
that an exception will not cause a class to be left in an unstable
state. For instance, you wouldn't want an OutOfMemoryException leaving
a container with an invalid size or missing elements.
Now, in C++, the main idea is to write code so that you do as much
work as possible withouth doing anything that can cause and exception,
and back track if something does go wrong. In C++, implementors
usually do this by using an idiom called, copy/modify/swap, to achieve
exception safety.
I am wondering if this is easier to do in C#. Assignment in C# has a
different meaning than assignment in C++ for reference types.
Assignment makes things equal, not equivelent. C# natively supports
Clone(), but not really a copy ctor. Since C# uses references, I can't
really change my reference since multiple references may be pointed to
the object I am modifying (some times).
Imagine there is a class that looks something like this:
class Dog
{
private int age = 0;
// . . .
public void CelebrateBirthday()
{
++age;
// . . . something throws an exception at this point
}
}
If I were to execute this code and an exception was thrown, my dog
would be a year older than he really should be (assuming that I want
to rollback (undo) the change in the face of an exception). One
solution would look like this:
public void CelebrateBirthday()
{
try
{
++age;
// . . . something throws an exception at this point
}
catch
{
--age;
// undo potential changes to other fields (may require storing
the old value)
}
}
Now, I would have to write that around every mutating method/property
in my class. YUCK! In a class with dozens of fields, that would be a
nightmare.
This is my proposed solution, similar to how it is done is C++:
private void copy(Dog dog)
{
age = dog.age;
// transfer additional fields
}
public void CelebrateBirthday()
{
Dog tempDog = new Dog();
tempDog.copy(this);
++tempDog.age;
// . . . something throws an exception at this point
this.copy(tempDog);
}
Notice that there is no longer a need for try/catch. If something goes
wrong, the copy, tempDog, just gets wasted. The final line is to
update 'this' with the changes.
Now, this seems really simple to me. I have trouble believing that
someone didn't come up with something more general or correct (I think
mine is correct???). For instance, there is a lot to be concerned
about with deep/shallow copies.
Community-wide approaches are what I am looking for. Anyone?
Thanks,
Travis Parks