Constructors

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

Peter Morris [Droopy eyes software]

I have an object persistence framework I have written, this framework
expects every object to descend ultimately from PersistentObject and to have
a constructor (ObjectSpace objectSpace) so that objects may be recreated.

PersistentObject's constructor will do something like this

this.ObjectSpace = objectSpace;
objectSpace.RegisterObjectCreation(this);

The object space will record a reference to this new object + do something
like this

if (!IsLoadingFromDatabase)
newInstance.AfterConstruction();


The virtual AfterConstruction method on a class is therefore only ever
called when an object is initially created and not when it is recreated due
to being fetched from the database. This gives a good opportunity to create
composite objects etc. Here is my problem

public class CustomerAction : PersistentObject
{
public CustomerAction(Customer customer)
: base(customer.ObjectSpace)
{
this.Customer = customer;
}

protected override void AfterConstruction()
{
//Do some stuff with this.Customer
}
}

My problem is that this.Customer has not been set by the time
AfterConstruction is called.

1) new CustomerAction(someCustomer);
2) CustomerAction constructor is called
3) Base constructor (customer.ObjectSpace is called)
4) CustomerAction.AfterConstruction is called
5) CustomerAction constructor code is executed

Why oh why wont dotnet let me execute some of my own code before calling the
base constructor? I can do this in methods.

I find it so restrictive!
 
J

Joanna Carter [TeamB]

"Peter Morris [Droopy eyes software]" <[email protected]> a écrit
dans le message de %[email protected]...

| The virtual AfterConstruction method on a class is therefore only ever
| called when an object is initially created and not when it is recreated
due
| to being fetched from the database. This gives a good opportunity to
create
| composite objects etc. Here is my problem
|
| public class CustomerAction : PersistentObject
| {
| public CustomerAction(Customer customer)
| : base(customer.ObjectSpace)
| {
| this.Customer = customer;
| }
|
| protected override void AfterConstruction()
| {
| //Do some stuff with this.Customer
| }
| }

Then, if you are setting the Customer property from the constructor, why not
simply use the Customer property setter to do anything after the property is
set ?

| Why oh why wont dotnet let me execute some of my own code before calling
the
| base constructor? I can do this in methods.
|
| I find it so restrictive!

There is always a way around this, it just requires a change of perspective
:)

Joanna
 
G

Guest

Peter,
I don't mean to sound disrespectful, but I've observed that often when
people make complaints like yours it is because they have engineering flaws
in their code pattern, not because the Framework is "restrictive". Perhaps
you ought to consider refactoring your design pattern?
Peter
 
L

Laura T

"Why oh why wont dotnet let me execute some of my own code before calling
the base constructor? "

Oh, it's not dotnet problem. It's not a problem at all.
If you are a child (your object) of someone (your parent object), your
parent must be alive before you can be alive.
That's why it's mandatory that the parent object is constructed first before
your object.
Rethink your design.
 
T

Thomas T. Veldhouse

Laura T said:
"Why oh why wont dotnet let me execute some of my own code before calling
the base constructor? "

That works in C++ correctly [in my opinion], but it doesn't work in .NET. It
is very annoying to work around. I wish it were possible to put:

// constructor
public SubClass(int variable) {
// do something here
base(variable);
}
Oh, it's not dotnet problem. It's not a problem at all.
If you are a child (your object) of someone (your parent object), your
parent must be alive before you can be alive.
That's why it's mandatory that the parent object is constructed first before
your object.
Rethink your design.

I think it is inconvenient at best. You can easily do such things in C++
without issue.
 
J

Joanna Carter [TeamB]

"Peter Bromberg [C# MVP]" <[email protected]> a écrit dans le
message de news: (e-mail address removed)...

| I don't mean to sound disrespectful, but I've observed that often when
| people make complaints like yours it is because they have engineering
flaws
| in their code pattern, not because the Framework is "restrictive".
Perhaps
| you ought to consider refactoring your design pattern?

I'm sorry Peter, but I know Pete Morris' work and it is not flaws in his
engineering pracices.

Peter, like I, comes from a Delphi background; a language which allows code
before the call to the inherited constructor.

When you have used a language like Delphi or C++ that allows this practice,
then you tend to design towards the capabilities of those languages. Moving
to a different language that has different features does take some getting
used to and I guess that P.M. will have to refactor, just as I have.

However, moving existing design patterns to a different language is not a
trivial task, but it is definitely *not* because of design failures.

Joanna
 
J

Joanna Carter [TeamB]

"Laura T" <laura.t@_yahoo.com> a écrit dans le message de [email protected]...

| Oh, it's not dotnet problem. It's not a problem at all.
| If you are a child (your object) of someone (your parent object), your
| parent must be alive before you can be alive.
| That's why it's mandatory that the parent object is constructed first
before
| your object.
| Rethink your design.

This is almost arrogant and doesn't consider the fact that Peter is a
skilled programmer and is making the transition from Delphi, C#'s parent;
which does allow code before inherited constructor calls.

That's why you have to consider that if it weren't for Delphi, you wouldn't
be using C# :)

Joanna
 
T

Thomas T. Veldhouse

Joanna Carter said:
This is almost arrogant and doesn't consider the fact that Peter is a
skilled programmer and is making the transition from Delphi, C#'s parent;
which does allow code before inherited constructor calls.

If anything said:
That's why you have to consider that if it weren't for Delphi, you wouldn't
be using C# :)

Yahoo ... Pascal was late in the OO game ... and Borland did it with Turbo
Pascal (I used to love programming in TurboVision when the whole world was DOS
and DPMI).
 
J

Joanna Carter [TeamB]

"Thomas T. Veldhouse" <[email protected]> a écrit dans le message de (e-mail address removed)...

| If anything, C++ is C#'s parent. In reality, I think Java is <duck!!!>.

<g>

My allusion is to the fact that Anders Heijlsberg (sp?) was architect on
Delphi before doing the same for C# :)

Joanna
 
T

Thomas T. Veldhouse

Joanna Carter said:
"Thomas T. Veldhouse" <[email protected]> a ?crit dans le message de (e-mail address removed)...

| If anything, C++ is C#'s parent. In reality, I think Java is <duck!!!>.

<g>

My allusion is to the fact that Anders Heijlsberg (sp?) was architect on
Delphi before doing the same for C# :)

Gotcha ... I didn't know that. Good old Microsoft ate up its little cousin
;-)
 
P

Peter Morris [Droopy eyes software]

Oh, it's not dotnet problem. It's not a problem at all.
If you are a child (your object) of someone (your parent object), your
parent must be alive before you can be alive.

I don't think that is quite right. I believe that the object instance
exists immediately, all constructors actually do is to initialise the
members of the instance. So why can't I explicitly specify the order in
which initialisation occurs as I can with virtual methods?
 
P

Peter Morris [Droopy eyes software]

Then, if you are setting the Customer property from the constructor, why
not
simply use the Customer property setter to do anything after the property
is
set ?

Because the value should effectively be readonly. In such a case I'd like
to ensure that the code will not compile unless I pass a customer.

But there are other considerations too, for example

public Class1
{
public Class1(Customer customer)
{
this.Customer = Customer;
do some stuff with customer, create some child objects etc
}
}


public SpecialClass1 : Class1
{
public SpecialClass1(Customer customer) : base(customer)
{
//this class is special so needs some special checks first
if (!DoSpecialChecks(customer))
throw new SomeExceptionType("The special checks failed");
}
}

Why should I go through potentially lots of base constructors + create all
the child objects etc (which may be expensive to create in terms of
resources) only to eventually be denied the possibility of creating the
object instance? It would be much better as this

public SpecialClass1 : Class1
{
public SpecialClass1(Customer customer)
{
//this class is special so needs some special checks first
if (!DoSpecialChecks(customer))
throw new SomeExceptionType("The special checks failed");

base(customer);
}
}


Or what if the parent constructor expects an ObjectSpace?

public ChildClass : PersistentObject
{
public ChildClass(Customer customer)
{
if (customer == null)
throw new ArgumentNullException("ChildClass constructor - customer");
if (customer.ObjectSpace == null)
throw new ArgumentException("ChildClass constructor - customer has no
object space");

base(customer.ObjectSpace);
}
}

So instead of my nicely formatted + (more importantly) expected exception
types I get a NullReferenceException because I can't write the code exactly
how I just did, the base constructor is called before my code gets a chance
to execute.

There are lots of reasons why someone might want to initialise code before
the base constructor code executes, I find it quite restrictive that I
cannot do it.

Pete
 
J

Joanna Carter [TeamB]

"Peter Morris [Droopy eyes software]" <[email protected]> a écrit
dans le message de news: (e-mail address removed)...

| I don't think that is quite right. I believe that the object instance
| exists immediately, all constructors actually do is to initialise the
| members of the instance.

Not in .NET; even Delphi for .NET doesn't allow anything before the
inherited constructor.

..NET constructors really do create the object and until you have reached the
constructor in the root class of a hierarchy, the object does not yet exist.
That seems to be the model that .NET follows.

| So why can't I explicitly specify the order in
| which initialisation occurs as I can with virtual methods?

Because C# doesn't support virtual static methods and constructors are a
special case static method ?

Joanna
 
J

Joanna Carter [TeamB]

"Thomas T. Veldhouse" <[email protected]> a écrit dans le message de (e-mail address removed)...

| Gotcha ... I didn't know that. Good old Microsoft ate up its little
cousin
| ;-)

Whoa!! Delphi is still very much alive and well. What is more it is one of
the few languages that can provide a single code base that will compile to
both Win32 *and* .NET.

Joanna
 
J

Joanna Carter [TeamB]

"Peter Morris [Droopy eyes software]" <[email protected]> a écrit
dans le message de news: (e-mail address removed)...

| Because the value should effectively be readonly. In such a case I'd like
| to ensure that the code will not compile unless I pass a customer.

Then you can have a split-visibility property where the setter is less
visible than the getter

public Customer Customer
{
get { return customer; }
private set
{
// other stuff
customer = value;
}

| But there are other considerations too, for example
|
| public Class1
| {
| public Class1(Customer customer)
| {
| this.Customer = Customer;
| do some stuff with customer, create some child objects etc
| }
| }

| Or what if the parent constructor expects an ObjectSpace?
|
| public ChildClass : PersistentObject
| {
| public ChildClass(Customer customer)
| {
| if (customer == null)
| throw new ArgumentNullException("ChildClass constructor - customer");
| if (customer.ObjectSpace == null)
| throw new ArgumentException("ChildClass constructor - customer has no
| object space");
|
| base(customer.ObjectSpace);
| }
| }

Aaah! in this case, you can use a private static method to do the checks,
etc on the incoming parameter, something like this :

class CustomerAction
{
private Customer customer;

private static Customer DoSomething(Customer customer)
{
return customer;
}

private CustomerAction(Customer customer, object dummy) : base()
{
this.customer = customer;
}

public CustomerAction(Customer customer) : this(DoSomething(customer),
null) { }
}

Joanna
 
J

Jon Skeet [C# MVP]

Joanna Carter said:
| I don't think that is quite right. I believe that the object instance
| exists immediately, all constructors actually do is to initialise the
| members of the instance.

Not in .NET; even Delphi for .NET doesn't allow anything before the
inherited constructor.

.NET constructors really do create the object and until you have reached the
constructor in the root class of a hierarchy, the object does not yet exist.
That seems to be the model that .NET follows.

Nope. Otherwise virtual method calls being made from the constructor
couldn't run the overridden implementation in the derived class, which
they do.

In fact, C# *does* run code before the base class constructor - it
executes the variable initialisers. (Note that this is different from
Java, which doesn't even execute the variable initializers before
running the superclass constructor.)

Here's an example to prove my point:

using System;

class Base
{
internal Base()
{
Console.WriteLine ("Base constructor");
}
}

class Derived : Base
{
int x = MakeSomeCall();

public Derived()
{
}

static int MakeSomeCall()
{
Console.WriteLine ("Called from variable initializer");
return 0;
}

static void Main()
{
new Derived();
}
}

Look at the code in ildasm or reflector - the call to MakeSomeCall is
genuinely before the call to the base constructor.

I suspect the reason for disallowing arbitrary placement of base
constructor calls is because an object can't guarantee to operate
properly before its parent parts are properly initialised. Of course,
if you make calls to virtual methods in the constructor, you can end up
calling into a derived class before *that's* had a chance to fully
initialize, too - which is a reason not to do that.

However, it's more common to want to access things to do with your
parent than it is to want to call overridden methods in a constructor.

I usually find there are ways round this when I really want to do
something before the constructor code is executed.
 
J

Jon Skeet [C# MVP]

Peter Morris said:
Because the value should effectively be readonly. In such a case I'd like
to ensure that the code will not compile unless I pass a customer.

But there are other considerations too, for example

public Class1
{
public Class1(Customer customer)
{
this.Customer = Customer;
do some stuff with customer, create some child objects etc
}
}


public SpecialClass1 : Class1
{
public SpecialClass1(Customer customer) : base(customer)
{
//this class is special so needs some special checks first
if (!DoSpecialChecks(customer))
throw new SomeExceptionType("The special checks failed");
}
}

In this case I'd create a static method which returns a SpecialClass1,
and make the constructor private.

Or what if the parent constructor expects an ObjectSpace?

public ChildClass : PersistentObject
{
public ChildClass(Customer customer)
{
if (customer == null)
throw new ArgumentNullException("ChildClass constructor - customer");
if (customer.ObjectSpace == null)
throw new ArgumentException("ChildClass constructor - customer has no
object space");

base(customer.ObjectSpace);
}
}

In this case I'd write a static method which does the check, and call
that:

public ChildClass (Customer customer)
: base (RetrieveObjectSpace(customer))
{
...
}

static ObjectSpace RetrieveObjectSpace (Customer customer)
{
// Same checks as you would have had in the constructor
}

I'm not trying to defend the decision (I'm ambivalent about it) - just
giving you some workarounds.
 
J

Jon Skeet [C# MVP]

Aaah! in this case, you can use a private static method to do the checks,
etc on the incoming parameter, something like this :

class CustomerAction
{
private Customer customer;

private static Customer DoSomething(Customer customer)
{
return customer;
}

private CustomerAction(Customer customer, object dummy) : base()
{
this.customer = customer;
}

public CustomerAction(Customer customer) : this(DoSomething(customer),
null) { }
}

Actually, in this case the parent constructor expects a parameter, so
there's no need for the extra constructor - just the extra method.

However, the idea of putting in a dummy constructor is nice. Well, no,
not nice - horribly evil - but effective. Mmm...
 
M

Mark Wilden

Joanna Carter said:
Peter, like I, comes from a Delphi background; a language which allows
code
before the call to the inherited constructor.

When you have used a language like Delphi or C++ that allows this
practice,

This capability is not available in C++, IIRC.

///ark
 
J

Joanna Carter [TeamB]

"Jon Skeet [C# MVP]" <[email protected]> a écrit dans le message de (e-mail address removed)...

| Nope. Otherwise virtual method calls being made from the constructor
| couldn't run the overridden implementation in the derived class, which
| they do.

Huh ? You lost me there.

| In fact, C# *does* run code before the base class constructor - it
| executes the variable initialisers. (Note that this is different from
| Java, which doesn't even execute the variable initializers before
| running the superclass constructor.)

Picky ! :)

| I usually find there are ways round this when I really want to do
| something before the constructor code is executed.

Like... ?

Joanna
 

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