Constructors

  • Thread starter Peter Morris [Droopy eyes software]
  • Start date
L

Laura T

Maybe this gives some hints:
(from http://blogs.msdn.com/scottwil/archive/2005/01/14/353177.aspx)
"
Q:

would expect C# to either (a) call the base class method if the derived
class is not fully constructed (which seems bad), or (b) provide a syntax
for initializing derived class members using constructor arguments before
base class constructors run (which seems good, and is what C++ does).



My two questions to you are then:

a.. what's up with this? Is there some goodness here that I'm missing out
on? Because this seems like a big old gotcha waiting to happen, calling
virtual methods before the object is constructed.
b.. any thoughts on how my tester buddy Ian can make his derived class
work without petitioning the owner of the base class to stop calling virtual
methods from the constructor?
Thanks!



Eric


A:

We (C#, .NET guidelines, FxCop) discourage calling virtual methods from
constructors. Forbidding it outright would be hard to do--even if we only
allowed constructors to call non-virtual methods, those methods could in
turn call virtuals. Also, it is occasionally useful.



C++ takes an object through a progression of type identities as a
constructor executes--basically, each constructor updates the v-table after
its call to the base constructor returns. As a result, virtual calls in a
constructor never go deeper than the constructor's level of inheritance.
This scheme provides a certain amount of protection against observing
uninitialized instance variables in virtual methods, but I don't think it is
a particularly useful or intuitive model. Indeed, the notion that an object
goes through a progression of base types until it finally reaches its true
type (and vice versa on destruction) is rather odd, and you could even argue
incorrect.



Unlike C++, C# (or, more correctly, .NET) immediately assigns a newly
allocated object its true type. Thus, virtual call dispatch is consistent
across the entire lifetime of the object, but it is possible to receive
virtual calls before execution reaches a constructor body. The big
difference between C++ and .NET is that .NET always zeroes out the memory of
a newly allocated object before executing any constructor code. So, while
virtual methods may observe the zeroed out state of instance variables, they
will never observe an undefined state and type safety is not compromised.



BTW, .NET's behavior is consistent with most other OOP systems, Java
included. In fact, I don't know of any language but C++ that uses the
"multiple personalities" approach to object construction.



Anders

"

Larry Lard said:
Joanna said:
Delphi, C#'s [spiritual] parent
[...] does allow code before inherited constructor calls.

Perhaps someone could ask Anders Heljsberg why he changed his mind about
this?


--
Larry Lard
(e-mail address removed)
The address is real, but unread - please reply to the group
For VB and C# questions - tell us which version
 
L

Laura T

There is also a little analysis of C# constructors at JOT (an old one but
still actual AFAIK):

http://www.jot.fm/issues/issue_2002_11/article4

Larry Lard said:
Joanna said:
Delphi, C#'s [spiritual] parent
[...] does allow code before inherited constructor calls.

Perhaps someone could ask Anders Heljsberg why he changed his mind about
this?


--
Larry Lard
(e-mail address removed)
The address is real, but unread - please reply to the group
For VB and C# questions - tell us which version
 
T

Thomas T. Veldhouse

Jon Skeet said:
Use a thread-local (static) variable which is set in the static method
(see other solutions for how to introduce a call to a static method),
and then use it in the overridden method to populate the instance
variable.

Now excuse me while I wash my hands ;)

That still doesn't get "customer" set. Further, what you describe is a
blatant hack .. no offense intended.
But aren't you effectively introducing that anyway by having the
AfterConstruction method at all? You've got to explain why the
AfterConstruction method is present, and moving the logic to the
constructor just makes it more explicit (and therefore easier to
understand, IMO.)

While a method called "AfterConstruct" leads one down a logical path towards a
specific business case, there are many cases where a similar pattern may be
required or desired and .NET does not allow its implementation [in spite of
hacking in a thread safe static method to set a static variable when in fact
you want an instance based variable set that cares less about threads and in
fact the base class doesn't know about].
 
J

Jon Skeet [C# MVP]

Thomas T. Veldhouse said:
That still doesn't get "customer" set.

It does get customer set - in the overridden method.
Further, what you describe is a blatant hack .. no offense intended.

None taken, as I pointed that out myself :)
But aren't you effectively introducing that anyway by having the
AfterConstruction method at all? You've got to explain why the
AfterConstruction method is present, and moving the logic to the
constructor just makes it more explicit (and therefore easier to
understand, IMO.)

While a method called "AfterConstruct" leads one down a logical path towards a
specific business case, there are many cases where a similar pattern may be
required or desired and .NET does not allow its implementation [in spite of
hacking in a thread safe static method to set a static variable when in fact
you want an instance based variable set that cares less about threads and in
fact the base class doesn't know about].

It's true that it cuts out some patterns - but in my experience it's
not often hugely annoying. YMMV, of course.
 
P

Peter Morris [Droopy eyes software]

I agree that the way dotnet creates the object instance is correct (it is
how he did it in Delphi too) but I also think that advising against calling
virtual methods from constructors is only due to the fact that you cannot
specify exactly when to call the base constructor's code.

If dotnet would allow me to specify exactly when the base was called then
this recommendation could be dropped. I also think it would make writing
classes much more flexible, in fact I cannot see a negative effect of
changing this.


Pete
 
P

Peter Morris [Droopy eyes software]

Well, I tried but (e-mail address removed) doesn't seem to be a genuine
email address :)
 
P

Peter Morris [Droopy eyes software]

But aren't you effectively introducing that anyway by having the
AfterConstruction method at all? You've got to explain why the
AfterConstruction method is present, and moving the logic to the
constructor just makes it more explicit (and therefore easier to
understand, IMO.)

No matter which constructor is called for a class (there may be many) there
are certain common operations which need to be executed

Customer.Address = new Address(ObjectSpace);
Customer.SomeOtherCompositeObject = .........
etc

This is a common requirement for many of my persistence objects so adding a
virtual method into the base persistent class makes perfect sense. If it
weren't called from a constructor then this is exactly how anybody would do
it - introduce common behaviour into a base class.

The pattern becomes very simple, instead of having code like this in
numerous base classes

{constructor}
CreateCompositeObjects();

private void CreateCompositeObjects()
{
if (!ObjectSpace.IsLoading)
{
....
}
}


All I have to do is to override AfterConstruction
protected override void AfterConstruction
{
...
}

If AfterConstruction is only called on "new" objects rather than fetched
objects being reinstanciated then I can effectively pretend that my objects
are not persistent at all. Separation is very important for keeping
business classes "clean", when was the last time you got into your car and
Saved it? :)

Pete
 
P

Peter Morris [Droopy eyes software]

It does get customer set - in the overridden method.

I don't really understand your suggestion. Is there any chance of some
suedo code?
 
L

Laura T

I think that the constructor behavior in .NET is just what is needed.
I mean, it's predictable, one way only and safe. It's quite uncommon, IMHO,
that there are other needs.
Dangling runtime initialization is somewhat risky as I see it, and harder to
manage.
And for the uncommon needs there are usually quite clean workaround.
 
J

Jon Skeet [C# MVP]

Peter Morris said:
I don't really understand your suggestion. Is there any chance of some
suedo code?

Sure.

using System;

public class Base
{
public Base()
{
AfterConstruction();
}

public virtual void AfterConstruction()
{
}
}

public class Derived : Base
{
[ThreadStatic]
static string temporaryName;

string m_name;

public Derived(string name) : this (SetStatic(name))
{
Console.WriteLine ("Now I'm in my own constructor");
}

Derived (int ignored)
{
}

static int SetStatic (string name)
{
temporaryName = name;
return 0;
}

public override void AfterConstruction()
{
m_name = temporaryName;
Console.WriteLine ("Validating name="+m_name);
}
}

class Test
{
static void Main()
{
Derived d = new Derived("fred");
}
}

The upshot is that in AfterConstruction which is called from the base
class, you can still have the arguments to derived constructor
available.
 
J

Jon Skeet [C# MVP]

Peter Morris [Droopy eyes software] <[email protected]>
wrote:

If AfterConstruction is only called on "new" objects rather than fetched
objects being reinstanciated then I can effectively pretend that my objects
are not persistent at all. Separation is very important for keeping
business classes "clean", when was the last time you got into your car and
Saved it? :)

Except you can't pretend that your objects aren't persistent - you need
to know in what situations AfterConstruction will be called, and in
particular you need to know that AfterConstruction may be called before
your object is fully initialized. You need to know why that is - in
other words, because it's persistent.

The same logic is expressed either way, IMO.
 
T

Thomas T. Veldhouse

Jon Skeet said:
Peter Morris said:
I don't really understand your suggestion. Is there any chance of some
suedo code?

Sure.

using System;

public class Base
{
public Base()
{
AfterConstruction();
}

public virtual void AfterConstruction()
{
}
}

public class Derived : Base
{
[ThreadStatic]
static string temporaryName;

string m_name;

public Derived(string name) : this (SetStatic(name))
{
Console.WriteLine ("Now I'm in my own constructor");
}

Derived (int ignored)
{
}

static int SetStatic (string name)
{
temporaryName = name;
return 0;
}

public override void AfterConstruction()
{
m_name = temporaryName;
Console.WriteLine ("Validating name="+m_name);
}
}

class Test
{
static void Main()
{
Derived d = new Derived("fred");
}
}

The upshot is that in AfterConstruction which is called from the base
class, you can still have the arguments to derived constructor
available.

Still not threadsafe ... one thread can overwrite temporaryName before the
original thread retrieves it. Have to do more work than that to make it
truly thread safe.
 
T

Thomas T. Veldhouse

Thomas T. Veldhouse said:
Still not threadsafe ... one thread can overwrite temporaryName before the
original thread retrieves it. Have to do more work than that to make it
truly thread safe.

Oops ... ignore my previous post. Threadstatic puts the static variable on
the thread's stack rather than the process stack.
 
B

Barry Kelly

Thomas T. Veldhouse said:
Oops ... ignore my previous post. Threadstatic puts the static variable on
the thread's stack rather than the process stack.

No, it uses TLS - Thread Local Storage. It's nothing to do with stacks.

-- Barry
 
B

Barry Kelly

Thomas T. Veldhouse said:
Everything with "static" has to do with "stack".

Historically, 'static' refers to how a variable is linked in C. In that
case, 'static' means it's not dynamically allocated (local variables and
heap variables are both dynamically allocated), but instead, space is
physically reserved in the image by the linker (typically in the BSS
section, which is zero-filled and is usually a "phantom" section in that
the data isn't actually in the executable image).

So, static is actually the complete opposite of the two dynamic things -
static and heap.

-- Barry
 
B

Barry Kelly

Barry Kelly said:
Historically, 'static' refers to how a variable is linked in C. In that
case, 'static' means it's not dynamically allocated (local variables and
heap variables are both dynamically allocated), but instead, space is
physically reserved in the image by the linker (typically in the BSS
section, which is zero-filled and is usually a "phantom" section in that
the data isn't actually in the executable image).

Or in the 'data' segment if there's initialization data, of course.

-- Barry
 
T

Thomas T. Veldhouse

Barry Kelly said:
Historically, 'static' refers to how a variable is linked in C. In that
case, 'static' means it's not dynamically allocated (local variables and
heap variables are both dynamically allocated), but instead, space is
physically reserved in the image by the linker (typically in the BSS
section, which is zero-filled and is usually a "phantom" section in that
the data isn't actually in the executable image).

Static has always meant the variable is pushed to the stack. It has also
meant that the scope points to the class rather than the instance. In C, the
scope has a slightly different meaning and points to the file/module that the
variable is declared in.

In the case where we are talking Thread Local Storage, the definition of
static is essentially changed to point the stack [that static is referring to]
from the process to the thread; thus, the thread has its own stack and the
static keyword will not point the variable to it .. the relative scope remains
the same and just the stack changes [to the threads local stack].
So, static is actually the complete opposite of the two dynamic things -
static and heap.

It is stack and heap. You just illustrated my point exactly. Static points
to the stack. In C++, the new keyword allocates on the heap, and in C, malloc
(or calloc) allocates on the heap. With .NET, it is a little more complicated
because we are dealing with a virtual machine, but within the virtual machine,
the logic remains the same.
 
B

Barry Kelly

Thomas T. Veldhouse said:
Static has always meant the variable is pushed to the stack.

Can you point to some online references that back this terminology /
statement?

When talking about modern imperative programming languages, the 'stack'
is understood to mean the CPU stack. Static variables do *not* allocate
storage on the CPU stack.
In C, the
scope has a slightly different meaning and points to the file/module that the
variable is declared in.

A static variable in global scope has internal linkage, yes - but all
variables declared in global scope are global variables, effectively the
same thing as C#'s static fields.

When you declare a static variable inside a function in C or C++, it
explicitly *prevents* the variable from being allocated on the stack,
and forces it to be allocated statically in the executable image - i.e.
it becomes a lexically scoped variable with static storage duration, IOW
lasting until the end of the program.
In the case where we are talking Thread Local Storage, the definition of
static is essentially changed to point the stack [that static is referring to]
from the process to the thread; thus, the thread has its own stack and the
static keyword will not point the variable to it .. the relative scope remains
the same and just the stack changes [to the threads local stack].

I think you're confused with your terminology. There's no such thing as
a process stack, only a stack per thread.

My mistake above: should be: static is opposite of two dynamic things -
automatic (i.e. local) and heap.
It is stack and heap.

There are three (3) storage durations available in unmanaged languages
like C and C++ (for C++, I'll refer you to ISO 14882 section 3.7):

1) Static: all objects which aren't dynamic or automatic
2) Automatic: all objects allocated as locals on the stack, expected to
be the CPU stack, associated with the current activation record
3) Dynamic: dynamic allocation via new & delete, new[] & delete[], or
malloc() & free().
You just illustrated my point exactly. Static points
to the stack.

Static is not on the stack. Local (i.e. automatic) variables are on the
stack - though that isn't strictly true in C# 2.0 with iterators and
variables captured through anonymous delegates, in which case they're on
the heap.

-- Barry
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top