> Someone commented that 'the object is not constructed' if an exception
> is thrown from the constructor, but that's not true.

This is true in C++ (unmanaged) - when a constructor throws an exception
(while new is being performed), then just-allocated memory must be freed by
the runtime. Since a caller will not receive a pointer, it will also be
unable to free it manually (additionally, calling delete on such a pointer
would be problematic). Of course, the memory allocated in a constructor will
only be freed if appropriately arranged (e.g, using auto_ptr() or a similar
schema).

> It's true that a
> reference to the new instance is not returned, but the instance is
> always 'created' (I'm not sure what the definition is 'construction' is
> in this case, but certainly an object id is allocated, etc.). This is
> obviously the case, since you have access to the 'this' pointer inside
> the constructor.

Right - and I do not fully remember object initialization details, but when
a constructor starts execution, the object has already its fields
initialized (to default values or some other values), so it exists.
Moreover, I believe that there is another difference from C++ - a base
class' constructor may call virtual methods (that refer to
not-yet-constructed derived class' object) - this is not elegant and this is
an error in many cases, but is possible. In C++ (unmanaged), if my memory
serves well, this is undefined and generally is a serious application error.
Maybe due to different vtable initialization rules (mentioned in one of
earlier posts). E.g., in C++, it is possible to call "pure virtual function"
in such a way.

> I hacked something together to check this out. As a result I've come up
> with a new coding rule for myself: 'if the constructor is going to
> throw, then the constructor has to guarantee that it hasn't configured
> another instance with a reference to itself'.

I would change this rule to the following: Do not pass a reference to itself
anywhere until the object is fully functional (configured). Even if the
constructor is "not going to throw" (theoretically, every line of code can
throw something ;-) ), what will happen if other threads start using the
object in an uninitialized state? What means that:
- if a constructor has to pass a reference to itself, it will do it in "the
last line of code"
- care should be taken for non-sealed classes (!)

> If you run this code, you'll see three partially constructed classes
> handle the publisher's event. This is definitely something to watch out
> for.

I would say that they are completely constructed but not completely
initialized (but will not fight for words).

> At the end of the day, I tend to think of exceptions as being too
> difficult to handle. I design my code such that exceptions don't happen.

I think that you are going definitely too far. Exceptions are a great way of
error reporting and handling, but as everything, there are always some
problems involved. Are you still using the "old-good" C-style with a
returned status? In a programming language with automatic GC? Interesting.

> If they do, then I have a bug and I need to fix it, I don't pretend that
> I can really 'handle' an exception (obviously there are cases where you
> have to, but I try to avoid these), despite its politically correct name
> I still consider it an 'error' and I generally terminate my process. To
> try and handle all the possible states that you could be in when you
> receive an exception seems almost impossible to me.

How about ThreadInterruptedException? How about temporary communication
errors? Etc. There are lots of errors that could be gracefully handled by an
application.

>       // construct and detach three subscribers
>       for (Int32 i = 0; i < 3; i++) {
>
>         try {
>           // try to construct a subscriber
>           subscriber = new EventSubscriber(publisher);
>         }
>         catch {
>           // ignore construction exception
>         }
>
>         if (subscriber != null) {
>           // construction was successfull, now detatch
>           // NOTE: this won't execute in this example as construction
>           // is never successful, meaning we can't detach the
>           // subscriber
>           subscriber.Detach();
>         }
>       }

A small remark: Note that if the first object would succeed and the
remaining two failed, then the first one would be Detach()ed three times.

Marek

===================================
This list is hosted by DevelopMentorŪ  http://www.develop.com
Some .NET courses you may be interested in:

NEW! Guerrilla ASP.NET, 17 May 2004, in Los Angeles
http://www.develop.com/courses/gaspdotnetls

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to