Exception in Constructor

  • Thread starter Thread starter TarheelsFan
  • Start date Start date
T

TarheelsFan

What happens whenever you throw an exception from within a constructor?
Does the object just not get instantiated?

Thanks for replies.
 
What happens whenever you throw an exception from within a constructor?
Does the object just not get instantiated?

Thanks for replies.

Well, the object certainly gets created on the heap, but once the
constructor exits with an exception you have no way of getting at the
instantiated object.

The object is surely allocated, because the constructor is supposed to
fill it in. So, before the constructor is called there is memory
allocated for the instance. If the constructor fails, the memory just
doesn't finish getting filled with values.

However, since the constructor throws an exception, any reference
variable where you were hoping to assign the instance reference will
remain uninintialized. So, for example, if you say

Person p = new Person("Harry");

then after the exception, p will remain uninitialized, because the
constructor never finished its job.

The orphaned memory will then be cleaned up by the Garbage Collector.
 
TarheelsFan said:
What happens whenever you throw an exception from within a constructor?
Does the object just not get instantiated?

(1) The object doesn't get instantiated, so I think its finalizer won't ever
run.
(2) Whoever tried to create an instance has to deal with the exception.
(3) As Bruce said, since the exception breaks you out of the try block that
would have assigned a reference to the new object, it's unrooted. The GC
will reclaim the memory, along with any objects only reachable from the
aborted construction. I think that if those objects were constructed fully,
their finalizers will run. If such subobjects need to be disposed, then
your constructor should do that before throwing the exception, because
otherwise. Of course, any changes you made to global program state before
throwing will be visible.

I don't know what happens if the constructor saved the this reference in
another object. It would be worth a try to investigate that. For example:

class Ugly
{
public static Ugly Singleton = null;
public Ugly()
{
Singleton = this; // The Spec# compiler won't let you, because
this isn't fully constructed yet
throw new NotImplementedException();
}
static void Main()
{
try {
Ugly stepsister = new Ugly();
}
catch (Exception) {}
// do something with Singleton???
}
}
 
I'm horribly wrong:
(1) The object doesn't get instantiated, so I think its finalizer won't
ever run.

The object IS instantiated as of the moment the user-defined starts running,
which is incidentally the first place you can use the this pointer (unless
you had inheritance, I see an even more evil example coming up). The
finalizer IS run.
(2) Whoever tried to create an instance has to deal with the exception.

Just like C++ two-phase construction. The caller's assignment of the
constructed object can't happen, because it's necessarily inside the try
block being exited, but the instance can be referenced elsewhere.


public class Ugly : IDisposable
{
public static Ugly Singleton;
public Ugly()
{
System.Diagnostics.Trace.WriteLine("in Ugly::.ctor");
Singleton = this;
throw new NotImplementedException();
}
~Ugly()
{
System.Diagnostics.Trace.WriteLine("in Ugly::.dtor");
}
public void Dispose()
{
System.Diagnostics.Trace.WriteLine("in Ugly::Dispose");
}
public static void Main()
{
try
{
Ugly stepsister = new Ugly();
}
catch (Exception) { }
System.Diagnostics.Trace.WriteLine("first " +
Ugly.Singleton.ToString());
try
{
using (Ugly stepsister = new Ugly()) { }
}
catch (Exception) { }
System.Diagnostics.Trace.WriteLine("second " +
Ugly.Singleton.ToString());
}
}


in Ugly::.ctor
A first chance exception of type 'System.NotImplementedException' occurred
in UselessJunkForDissassembly.exe
first UselessJunkForDissassembly.Ugly
in Ugly::.ctor
A first chance exception of type 'System.NotImplementedException' occurred
in UselessJunkForDissassembly.exe
second UselessJunkForDissassembly.Ugly
The thread 0xfc4 has exited with code 0 (0x0).
The thread 0xf3c has exited with code 0 (0x0).
in Ugly::.dtor
in Ugly::.dtor
 
Well, apparently the most-derived object is already alive before *any* user
constructor code starts running. It's effectively the same as two-phase
construction. This lets you call virtual methods virtually from the
constructor I guess, don't let your virtual methods rely on the constructor
previously running:


public abstract class Ugly : IDisposable
{
public static Ugly Singleton;
public Ugly()
{
System.Diagnostics.Trace.WriteLine("in Ugly::.ctor");
Singleton = this;
throw new NotImplementedException();
}
~Ugly()
{
System.Diagnostics.Trace.WriteLine("in Ugly::.dtor");
}
public virtual void Dispose()
{
System.Diagnostics.Trace.WriteLine("in Ugly::Dispose");
}
public static void Main()
{
try
{
Ugly stepsister = new Uglier();
}
catch (Exception) { }
System.Diagnostics.Trace.WriteLine("first " +
Ugly.Singleton.ToString());
try
{
using (Ugly stepsister = new Uglier()) { }
}
catch (Exception) { }
System.Diagnostics.Trace.WriteLine("second " +
Ugly.Singleton.ToString());
}
}

public class Uglier : Ugly, IDisposable
{
public Uglier()
: base()
{
System.Diagnostics.Trace.WriteLine("in Uglier::.ctor");
Singleton = this;
throw new NotImplementedException();
}
~Uglier()
{
System.Diagnostics.Trace.WriteLine("in Uglier::.dtor");
}
public override void Dispose()
{
System.Diagnostics.Trace.WriteLine("in Uglier::Dispose");
}
}

in Ugly::.ctor

A first chance exception of type 'System.NotImplementedException' occurred
in UselessJunkForDissassembly.exe

first UselessJunkForDissassembly.Uglier

in Ugly::.ctor

A first chance exception of type 'System.NotImplementedException' occurred
in UselessJunkForDissassembly.exe

second UselessJunkForDissassembly.Uglier

The thread 0x9bc has exited with code 0 (0x0).

The thread 0xe80 has exited with code 0 (0x0).

in Uglier::.dtor

in Ugly::.dtor

in Uglier::.dtor

in Ugly::.dtor
 
Hi Ben,
This lets you call virtual methods virtually from the constructor I guess

You shouldn't call virtual methods from within the constructor since the
constructor of derived classes will not have executed yet even though it may
be the derived method that's invoked.
 
Dave Sexton said:
Hi Ben,


You shouldn't call virtual methods from within the constructor since the
constructor of derived classes will not have executed yet even though it
may be the derived method that's invoked.

I agree that you shouldn't call (any) methods from a constructor without
documenting that fact. I can definitely see where it would have its uses
though. I think this is very different from C++ though, because I think in
C++ the v-table doesn't hold the members in the derived class until the
derived constructor starts.

It would be interesting to find out what order field initializers are run...
are derived class fields using initializer syntax initialized before the
base constructor runs?
 
It would be interesting to find out what order field initializers are run...
are derived class fields using initializer syntax initialized before the
base constructor runs?

Derived field initializers are called, then the base field
initializers, then the base constructor, then the derived constructor.
Note that this is different to Java, which runs the base constructor
before the field initializers.

See http://www.yoda.arachsys.com/csharp/constructors.html for more
information.
 
Dave Sexton said:
Hi Ben,

The problem with calling a virtual method from a constructor is that
fields

It's not a "problem", its documented, reliable behavior that has to be
considered in the design. Drawback perhaps, but not exactly a problem.
 
Hi Ben,

I see it as a big problem. There are more flexible designs that can be used
instead of calling a virtual method from a constructor, and no amount of
documentation is going to make that architecture flexible. Also, it's not
intuitive at all, which may cause problems when developers make assumptions
that are normally safe about the order of initialization of their derived
class.

I also disagree that the behavior is "reliable". A base class that calls a
particular virtual method from within a constructor might also defer the
call to the same virtual method depending upon a constructor argument or
some other internal state. The overridden method would have to check some
initialization variable to determine whether its fields have been
initialized or not - and that's if the developer is aware of this strange
behavior in the first place.
 
Dave Sexton said:
The problem with calling a virtual method from a constructor is that fields
in the derived class might not be initialized before the override is called:

I'm sure Ben knows that, but it can still be useful.
Visual Studio Team System
Do not call overridable methods in constructors
http://msdn2.microsoft.com/en-us/library/ms182331(VS.80).aspx

This is a rule from FxCop's successor, right? It's only a
recommendation, not a law. FxCop lost my vote when it kept on moaning
about my IEnumerable TreeSet not ending in the word 'Collection'.

-- Barry
 
Hi Barry,

I think I've given good enough reasons as to why it should be avoided.
Simply saying that's it can still be useful doesn't prove anything. VB 6
can still be useful :)
 
Ben said:
I agree that you shouldn't call (any) methods from a constructor without
documenting that fact. I can definitely see where it would have its uses
though. I think this is very different from C++ though, because I think in
C++ the v-table doesn't hold the members in the derived class until the
derived constructor starts.

As a point of interest, the C# / .NET semantics match Delphi semantics,
and Delphi similarly zeros memory before starting on the constructor.
Delphi also invokes the destructor even if the constructor threw an
exception; this is OK because the memory is already zero-filled.

Folks in the Delphi world have always wondered about the C++ way of
doing it in reverse :)

-- Barry
 
I hadn't thought about this before. Does this mean I should try/catch
in my IDisposable class constructors when I'm allocating a disposable
or unmanaged resource in the ctr?

ollector.
 
JS said:
I hadn't thought about this before. Does this mean I should try/catch
in my IDisposable class constructors when I'm allocating a disposable
or unmanaged resource in the ctr?

If there is any possibility of failure between the creation of that
unmanaged resource and completing your constructor, yes. Proper use of the
RAII idiom avoids this. Note that your finalizer will be called even in the
case where the constructor throws.

If you're abusing exceptions to implement business logic in a long-running
process, then creation of disposable objects should be handled with
try/catch as well.

Any use of a synchronization lock must use try/catch, either implicitly with
the using block, or explicitly, because holding the lock until finalization
occurs will break things.
 
FxCop lost my vote when it kept on moaning
about my IEnumerable TreeSet not ending in the word 'Collection'.

No need to throw out the baby with the bathwater. Warnings - even compiler
warnings - are just aids to writing good code. Adhering to them doesn't
guarantee good code, and ignoring them does guarantee bad code.

I have always just turned off warnings (and FxCop rules) I don't agree with.

///ark
 
unmanaged resource and completing your constructor, yes. Proper use of the
RAII idiom avoids this. Note that your finalizer will be called even in the

When you say proper us of RAII, do you mean that the code calling the
constructor in question is wrapped in a 'using' block? And is this
guaranteed to call Dispose even if the constructor threw an exception?
 
Mark said:
No need to throw out the baby with the bathwater. Warnings - even compiler
warnings - are just aids to writing good code. Adhering to them doesn't
guarantee good code, and ignoring them does guarantee bad code.

Sure - as a compiler writer I agree. However, a compiler has a far, far
higher threshold of "pain" than a static checker like FxCop. FxCop
generated too many false positives when I first used it, and I developed
much antipathy towards it.

When I started using it, it gave me almost no useful information, and
caused much agony e.g. trying to add correct security attributes to my
server-side assemblies which already ran in a full-trust environment,
which then broke various things, and I had to add various security
assertions, and basically wasted lots of time trying to keep it happy.

I've seen much better things out of the stuff described e.g. in this
video:

http://video.google.com/videoplay?docid=-8150751070230264609&q=engEDU+static+analysis

.... i.e. common actual bugs. Design guidelines I can tolerate for things
like naming guidelines & spellcheck, and Dispose/Finalize, things that
are important to get right for consistency, and things that are easy to
get wrong.
I have always just turned off warnings (and FxCop rules) I don't agree with.

Actually, I'd prefer if it started with nothing and only opted into
things slowly, from an extremely high threshold, like a compiler.

-- Barry
 
JS said:
When you say proper us of RAII, do you mean that the code calling the
constructor in question is wrapped in a 'using' block? And is this
guaranteed to call Dispose even if the constructor threw an exception?

It's guaranteed to call Dispose whether or not the constructor throws
an exception - which probably isn't what you're after. You probably
want to call Dispose *only* if the constructor throws an exception.
 
Back
Top