473,421 Members | 1,500 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,421 software developers and data experts.

Exception in Constructor

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

Thanks for replies.

Jan 24 '07 #1
23 7190
On Jan 24, 12:40 pm, "TarheelsFan" <tsedw...@wingate.eduwrote:
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.

Jan 24 '07 #2

"TarheelsFan" <ts******@wingate.eduwrote in message
news:11**********************@a75g2000cwd.googlegr oups.com...
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???
}
}

>
Thanks for replies.

Jan 25 '07 #3

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:uA**************@TK2MSFTNGP06.phx.gbl...
>
"TarheelsFan" <ts******@wingate.eduwrote in message
news:11**********************@a75g2000cwd.googlegr oups.com...
>What happens whenever you throw an exception from within a constructor?
Does the object just not get instantiated?
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
Jan 25 '07 #4
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

Jan 25 '07 #5
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
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:eY**************@TK2MSFTNGP04.phx.gbl...
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

Jan 25 '07 #6

"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:Ox**************@TK2MSFTNGP04.phx.gbl...
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.
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?
>
--
Dave Sexton
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:eY**************@TK2MSFTNGP04.phx.gbl...
>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


Jan 25 '07 #7
Hi Ben,

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:

Visual Studio Team System
Do not call overridable methods in constructors
http://msdn2.microsoft.com/en-us/lib...31(VS.80).aspx

--
Dave Sexton
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:uk****************@TK2MSFTNGP06.phx.gbl...
>
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:Ox**************@TK2MSFTNGP04.phx.gbl...
>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.

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?
>>
--
Dave Sexton
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:eY**************@TK2MSFTNGP04.phx.gbl...
>>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



Jan 25 '07 #8
Ben Voigt <rb*@nospam.nospamwrote:

<snip>
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.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jan 25 '07 #9

"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:%2****************@TK2MSFTNGP06.phx.gbl...
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.
in the derived class might not be initialized before the override is
called:

Visual Studio Team System
Do not call overridable methods in constructors
http://msdn2.microsoft.com/en-us/lib...31(VS.80).aspx

--
Dave Sexton
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:uk****************@TK2MSFTNGP06.phx.gbl...
>>
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:Ox**************@TK2MSFTNGP04.phx.gbl...
>>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.

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?
>>>
--
Dave Sexton
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:eY**************@TK2MSFTNGP04.phx.gbl...
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





Jan 25 '07 #10
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
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:%2******************@TK2MSFTNGP03.phx.gbl...
>
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:%2****************@TK2MSFTNGP06.phx.gbl...
>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.
>in the derived class might not be initialized before the override is
called:

Visual Studio Team System
Do not call overridable methods in constructors
http://msdn2.microsoft.com/en-us/lib...31(VS.80).aspx

--
Dave Sexton
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:uk****************@TK2MSFTNGP06.phx.gbl...
>>>
"Dave Sexton" <dave@jwa[remove.this]online.comwrote in message
news:Ox**************@TK2MSFTNGP04.phx.gbl...
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.

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?
--
Dave Sexton
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Ben Voigt" <rb*@nospam.nospamwrote in message
news:eY**************@TK2MSFTNGP04.phx.gbl...
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
>
>
>




Jan 25 '07 #11
"Dave Sexton" <dave@jwa[remove.this]online.comwrote:
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/lib...31(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

--
http://barrkel.blogspot.com/
Jan 25 '07 #12
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 :)

--
Dave Sexton
http://davesexton.com/blog
http://www.codeplex.com/DocProject (Sandcastle in VS IDE)

"Barry Kelly" <ba***********@gmail.comwrote in message
news:33********************************@4ax.com...
"Dave Sexton" <dave@jwa[remove.this]online.comwrote:
>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/lib...31(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

--
http://barrkel.blogspot.com/

Jan 25 '07 #13
Ben Voigt wrote:
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

--
http://barrkel.blogspot.com/
Jan 25 '07 #14
JS
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.

Jan 26 '07 #15

"JS" <jn*********@gmail.comwrote in message
news:11**********************@k78g2000cwa.googlegr oups.com...
>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.
>
ollector.

Jan 26 '07 #16
"Barry Kelly" <ba***********@gmail.comwrote in message
news:33********************************@4ax.com...
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
Jan 26 '07 #17
JS
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?

Jan 26 '07 #18
Mark Wilden wrote:
"Barry Kelly" <ba***********@gmail.comwrote in message
news:33********************************@4ax.com...
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.
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?do...tatic+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

--
http://barrkel.blogspot.com/
Jan 26 '07 #19
JS <jn*********@gmail.comwrote:
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?
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.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jan 26 '07 #20
"Barry Kelly" <ba***********@gmail.comwrote in message
news:42********************************@4ax.com...
I had to add various security
assertions, and basically wasted lots of time trying to keep it happy.
I think this is the trap - trying to make a tool happy, instead of the other
way around. I've succumbed to it myself.
>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.
The thing about this approach is that you don't know what might be wrong
with your code that the tool can find and that you never even suspected.

That's why I'll run FxCop (or lint, or whatever), examine its output, then
turn off what I don't agree with.
Jan 29 '07 #21

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
JS <jn*********@gmail.comwrote:
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?

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.
No, it's not guaranteed, in fact it won't. When the constructor fails, the
outer block never receives a handle to the object, and therefore can't call
Dispose.

For this reason, a constructor should not throw while holding disposable or
unmanaged resources, it should free them before throwing (possibly by
calling its own Dispose method, then Dispose needs to be written to properly
handle partially constructed objects).
>
--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Feb 1 '07 #22

"JS" <jn*********@gmail.comwrote in message
news:11*********************@q2g2000cwa.googlegrou ps.com...
>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?
No, I mean that each external resource is handled by a class whose sole
responsibility is to manage that resource. Such a class cannot leak a
resource during construction, because the only possible exception is when
obtaining the resource.

Unmanaged C++ does far better than .NET in this regard, because when the
object's lifetime ends as a result of the constructor throwing, all
fully-constructed subobjects have their destructors run automatically. You
must explicitly call Dispose in .NET in the similar scenario to get
deterministic release of resources.
Feb 1 '07 #23
Ben Voigt <rb*@nospam.nospamwrote:
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.

No, it's not guaranteed, in fact it won't. When the constructor fails, the
outer block never receives a handle to the object, and therefore can't call
Dispose.
Indeed - I misread the previous post. I thought it was talking about
having a using block *inside* the constructor.
For this reason, a constructor should not throw while holding disposable or
unmanaged resources, it should free them before throwing (possibly by
calling its own Dispose method, then Dispose needs to be written to properly
handle partially constructed objects).
Agreed.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Feb 1 '07 #24

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Pierre Rouleau | last post by:
The std::exception class defined in the Standard C++ <exception> header specifies that the constructors could throw any exception becuase they do not have a throw() specification. Why is that? ...
11
by: Ivan A. | last post by:
Hi Is there any method to change System. Exception. Message property in derived exception's constructor? I need runtime class' information to initialize this property, but it's readonly. ...
4
by: JSheble | last post by:
If an exception occurs or is thrown in my constructor, what does the constructor actually return? A null?
8
by: JAL | last post by:
According to MSDN2, if a managed class throws an exception in the constructor, the destructor will be called. If an exception is thrown in the constructor the object never existed so how in the...
1
by: yancheng.cheok | last post by:
Hi all, According to "How can I handle a constructor that fails?" in http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.2, whenever there is a constructor fail, we will throw...
3
by: matko | last post by:
This is a long one, so I'll summarize: 1. What are your opinions on raising an exception within the constructor of a (custom) exception? 2. How do -you- validate arguments in your own...
4
by: Sunil Varma | last post by:
Hi, Here is a piece of code where the constructor throws an exception. class A { int n; public: A() try{
5
by: Vijay | last post by:
Hi All, I am not able to figure out what exactly happening in below code. what is control flow. Can anyone clear my confusion? Code: class A { public: A(){cout<<"In Constructor\n";}
11
by: Peter Jansson | last post by:
Dear newsgroup, In the following code, it looks as though the exception thrown in the constructor is not caught properly. I get this output: ---- standard output ---- Base() constructor....
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.