For Programmers: Free Programming Magazines  


Home > Archive > C# > February 2005 > Can a class's constructor call another constructor "later"?









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Can a class's constructor call another constructor "later"?
Joel Thornton

2005-02-09, 8:59 pm

In VB.NET it's possible for one constructor to call a 'sibling'
constructor at any point in its own implementation, e.g.

Public Sub New()
// do some other stuff first
MyBase.New(...)
End Sub


However in C# it appears the only syntax available for calling a
sibling constructor is this:

public SampleClass() : this(...) {
// this code executes ONLY after this(...) is executed
}

According to the docs this syntax causes the this(...) piece to be
executed first, before the implementation of the SampleClass()
constructor is executed. There's no option to execute it later on.

This is useful, for example, when you want a parameterless constructor
to compute a 'default' value, then pass it into a sibling parameterized
constructor. But there may be other times where the order of operations
is important and you need to do some kind of work before the secondary
constructor should be executed.


Is this correct? Am I missing something really obvious?

Joel

Bruce Wood

2005-02-09, 8:59 pm

No, you're not missing anything.

The constructor order in C# is much more strict, probably in an attempt
to stop programmers who really don't understand it all that well from
creating odd instantiation bugs. Most programmers assume that the base
class part of the object is instantiated and its properties and methods
are available to use in the child object's constructor code. If the
base class's constructor hasn't been called yet, then you can't trust
any of its properties / methods in your constructor code.

The way to get around this is usually to create a protected
initialization method that child classes are supposed to call in their
constructors:

public class myBase
{
public myBase(...) {...}
protected void initBase(...) {...}
}

public class myChild : myBase
{
public myChild(...) : base(...)
{
...do some stuff here...
base.initBase(...);
}
}

Pat

2005-02-10, 3:58 pm

Why would you want to get around the order of instantiation? That
would violate the rules of inheritance.

Bruce Wood

2005-02-10, 3:58 pm

Well, I don't know that it would violate any inheritance rules, per se,
but it does leave one open to all sorts of subtle errors.

The problem would be that you could initialize your child class's
members before you had initialized the base class members. However,
most people writing code inside a constructor assume that the base
class properties and methods are already available for use and may
invoke them from the child constructor. In the current model, where you
must construct the base object first, this is a safe assumption.
However, if you were allowed to delay calling the base class
constructor until "later", as the OP said, this would mean that base
properties and methods would exhibit undefined behaviour until that
constructor was called.

No doubt many programmers would forget that detail and introduce odd
errors into their constructor code.

Joel Thornton

2005-02-11, 8:58 pm

Thanks for the info Bruce, that makes (enough) sense.

Pat, I think what really thew me for a loop is the fact that this kind
of "late constructor calling" syntax is supported in VB.NET but not in
C#, and I was working through an MSDN article whose examples were only
in VB.NET and used this syntax.

Thanks again all.

Bruce Wood

2005-02-16, 4:01 pm

I suppose that this is a "pit"... if, as Alex said in his 'blog, the
coffee is wearing off. I find the current constructor behaviour
(particularly as he wrote it in his class) perfectly obvious:

public SecurityManager(User user) : this() {
this._user = user;
}

The call after the colon _always_ happens first. It has nothing to do
with "constructor overrides behave in the opposite way to method
overrides." I have no idea how he arrives at that conclusion. The
difference with constructor overrides is that the call order is
_fixed_: you can't insert a this() call or a base() call wherever you
like. It always comes first. The method override example he gave is
really a bit of a cheat because it calls the base method at the end,
illustrating nothing more than that when you override a method you can
choose to call the base method wherever you like, or not at all.

Constructor overrides, on the other hand, act like method overrides
that give you no choice where the base constructor is called: it is
always called at the beginning.

As well, I should point out that what Alex did in his first example
(the code with the bug in it, illustrated above) is bad constructor
form. Wherever possible, you should code constructors that take fewer
parameters to call those that take more parameters, _not_ the other way
around. His changed solution illustrates correct form:

public class SecurityManager {
public SecurityManager () : this(null) {
}

public SecurityManager(User user) {
this._user = user;
if(user == null) {
this._user = User.CurrentUser;
}
InitialiseData();
}
private User _user;
}

The constructor with no parameters calls the one-parameter constructor,
passing it a default value for the parameter: in this case, a null. I
call this "correct form" because it is much easier to follow what's
going on, and far more difficult to make the kinds of mistakes that
Alex pointed out in his 'blog.

David Dindorp

2005-02-17, 9:02 am

Hm. Yes. I agree completely with you that in Alex' case, his fixed
syntax is more correct.

That said, the blog link was a bad example since it's a completely
different beast. Alex uses only a single class, no inheritance, and
there's obviously a perfectly fine solution to his particular problem.
I merely included it to illustrate that even people doing simple
constructor->constructor calls are having problems following the logic
that the C# limitations impose on their programming. I guess the only
relevant part of the example was really the first comment - quote: "Dare
I say it, but this is one spot where I think the VB syntax definately
removes confusion".

My point was that the VB.Net way of doing things (which resembles how
it's done in other user-friendly programming languages, eg. Delphi) is
much less error-prone and much less frustrating for the developer.
IMHO, most developers hate doing ugly kludges like what is needed here,
because they are error-prone and because they introduce entire methods
that are just a waste of lines of code, nothing else. Giving the
developer the choice of when to call the super-class constructor (with a
default of 'first') is as clear as it can get, and C# unfortunately does
not support it.

I might not have made myself completely clear in my first posting, so
I'll try a code example. I'm pretty bad at examples, so try and keep up
:-).

Let's say I have a bunch of different components I'm developing, and for
the sake of this example, they're all implemented as background
services. They communicate over the network with a central logging
facility, a relational database, and several coffee makers. The code
that connects to these devices are pretty much the same for all the
services. Additionally, the services cannot function at all without
access to the database where their data is stored, and are (for
management purposes) not allowed to start if the logging facility is not
available.

Since the database and logging facility initialization code is shared
and needs to always run, the developer finds that it's a natural choice
to implement it in a super-class and make sure it's called in the
super-class constructor. All services derive from this class and thus
performs the initialization as the first thing.

However, in order to uniquely identify each service running on the
network, they must have a unique id. This is used to log
start/stop/whatever messages to the central logging facility.

Depending on the particular kind of service, they need to get this id
from a specific pool of id's.

For instance, federal regulation requires that all services which are
related to doing datamining for customers selling large quantities of
red wine (RedWineDataAnalyzer services) need to retrieve their unique id
from a bowl of petunias reachable over the network. The bowl of
petunias is situated in a federal institution, and designates id's that
are unique across multiple data mining institutions approved by the
government. (The reason that it's a bowl of petunias is that it was
designed by the government's military/defense wing, and they went
under-budget and needed to burn some money before the new year.)

All services related to controlling greenhouse irrigation needs to get
their id's from a pool of muddy water, also reachable over the network.

The interface to communicating with the bowl of petunias and the pool of
muddy water is of course quite different, therefore it made sense for
the developer to implement that code in the service sub-classes.

Now here is the problem: The shared code must always run, thus it is in
the constructor (of the super-class). But the (sub-class) non-shared
code which is needed to provide an interface to the id-assigning bowl of
petunias and pool of muddy water needs to be called first. How is this
done in C#, you ask? Like this, perhaps:

===========================
class Service {
protected string id = null;

private void connectToLoggingFacility() { .. use id .. }
private void logServiceStart() { .. use id .. }
private void connectoToDb() { .. use id .. }

public Service() {
connectToLoggingFacility();
logServiceStart();
connectoToDb();
}
}

class RedWineDataAnalyzerService {
private void retrieveIdFromPetunias() { .. set id .. }

public RedWineDataAnalyzerService() {
retrieveIdFromPetunias();
base();
}
}
===========================

..... no, because the base constructor is implicitly and effectively
always called first in C#.
You have to do something like this:

===========================
class Service {
protected string id = null;

private void connectToLoggingFacility() { .. use id .. }
private void logServiceStart() { .. use id .. }
private void connectoToDb() { .. use id .. }

protected virtual void retrieveIdFromWhatever() {
// blank method
}

public Service() {
retrieveIdFromWhatever();
connectToLoggingFacility();
logServiceStart();
connectoToDb();
}
}

class RedWineDataAnalyzerService {
protected override void retrieveIdFromWhatever() {
// Connect to bowl of petunias and retrieve id here.
// If you forget the 'override' keyword, you're screwed.
}

public RedWineDataAnalyzerService(): base() {
retrieveIdFromPetunias();
}
}
===========================

Let's assume that someone, long ago employed at the company in question,
implemented the super-class. Now someone else has to create a new
service which answers telephones. Looking at the first example, he
would instinctly know that during construction of the service, he needs
to first retrieve a unique ID, then to have the super-class constructor
do whatever magic it does.

Unfortunately, noone at the company documents any code, and our guy has
only the second example (using correct C# syntax) to go after. He looks
at the code for the RedWineDataAnalyzer service and copies bits and
pieces from it. He has no clue what retrieveIdFromWhatever is used for,
and he can't tell from the RedWineDataAnalyzer code when it's called,
thus he decides to leave it out. This has the effect that his telephone
answering machine services does not log to the central logging facility.
Noone immediately discovers this, but it means that management has no
idea where they are installed or when they run.

Results are that, over time, rogue telephone answering machine services
all over the company, long forgotten, from time to time kicks in and
answers telephones with product prices from a decade ago, which the
company then has to abide by, thus they eventually go bankrupt.

Conclusion:
Asides from being a kick in the groin to the developers, the C# syntax
causes bankruptcy and, through the distinction of healthy development
firms, economic recession.

The example given is perhaps a bit excessive, but I hope it proves the
point - the current limitations on syntax is counter-intuitive and
confusing to developers.
Bruce Wood

2005-02-17, 4:04 pm

First, it's easy to fix your example in order to avoid bankruptcy and
worldwide economic collapse. Simply code Service like this:

abstract class Service
{
protected string id =3D null;

private void connectToLoggingFacility() { }
private void logServiceStart() { }
private void connectoToDb() { }

protected abstract void retrieveIdFromWhatever();

public Service()
{
retrieveIdFromWhatever();
connectToLoggingFacility();
logServiceStart();
connectoToDb();
}
}

The "abstract" declaration requires child classes to implement
retrieveIdFromWhatever... voil=E0: disaster averted.

Nonetheless, I see your point. There are good arguments for both the VB
and C# way of doing construction. I can see that the VB.NET way of
doing things would appeal more to veteran programmers who are aware of
the risks involved and want the added flexibility. I, too, have been
stuck once or twice, but on a simpler example than yours: what if you
need to pass an argument to the base constructor, but you need to do
some complex calculation in order to derive that argument? In C# you're
stuck, and have to resort to an initialization method. In VB.NET you
could do the calculation and then call base() afterward.

However, I can also see the point of doing it the Java / C# way (Java
does it the same way, by the way): it's safer.

Funny, though, since C# is sold as the more programmer-savvy, strict
language, and VB.NET is sold as the "easy to use," "easy-going"
language.

David Dindorp

2005-02-18, 8:57 am

Bruce Wood wrote:
> First, it's easy to fix your example in order to avoid bankruptcy and
> worldwide economic collapse. Simply code Service like this:

[snip]
> The "abstract" declaration requires child classes to implement
> retrieveIdFromWhatever... voilą: disaster averted.


Hm! Had thought that you were only allowed to have abstract methods in
abstract classes. I learn. Great, thanks :-).

[snip]
> However, I can also see the point of doing it the Java / C# way (Java
> does it the same way, by the way): it's safer.


Pardon my inquisitive nature, we should probably have ended this
pointless discussion long ago. But I have to ask, safer for whom or
what? Not for the novice developer who is forced to place the base()
out of context and wonder when it's called (before or after), I hope?

> Funny, though, since C# is sold as the more programmer-savvy, strict
> language, and VB.NET is sold as the "easy to use," "easy-going"
> language.


"Funny", "annoying as hell", whichever :-).
Bruce Wood

2005-02-21, 3:58 am

I suppose that this is a "pit"... if, as Alex said in his 'blog, the
coffee is wearing off. I find the current constructor behaviour
(particularly as he wrote it in his class) perfectly obvious:

public SecurityManager(User user) : this() {
this._user = user;
}

The call after the colon _always_ happens first. It has nothing to do
with "constructor overrides behave in the opposite way to method
overrides." I have no idea how he arrives at that conclusion. The
difference with constructor overrides is that the call order is
_fixed_: you can't insert a this() call or a base() call wherever you
like. It always comes first. The method override example he gave is
really a bit of a cheat because it calls the base method at the end,
illustrating nothing more than that when you override a method you can
choose to call the base method wherever you like, or not at all.

Constructor overrides, on the other hand, act like method overrides
that give you no choice where the base constructor is called: it is
always called at the beginning.

As well, I should point out that what Alex did in his first example
(the code with the bug in it, illustrated above) is bad constructor
form. Wherever possible, you should code constructors that take fewer
parameters to call those that take more parameters, _not_ the other way
around. His changed solution illustrates correct form:

public class SecurityManager {
public SecurityManager () : this(null) {
}

public SecurityManager(User user) {
this._user = user;
if(user == null) {
this._user = User.CurrentUser;
}
InitialiseData();
}
private User _user;
}

The constructor with no parameters calls the one-parameter constructor,
passing it a default value for the parameter: in this case, a null. I
call this "correct form" because it is much easier to follow what's
going on, and far more difficult to make the kinds of mistakes that
Alex pointed out in his 'blog.

David Dindorp

2005-02-21, 8:57 am

Hm. Yes. I agree completely with you that in Alex' case, his fixed
syntax is more correct.

That said, the blog link was a bad example since it's a completely
different beast. Alex uses only a single class, no inheritance, and
there's obviously a perfectly fine solution to his particular problem.
I merely included it to illustrate that even people doing simple
constructor->constructor calls are having problems following the logic
that the C# limitations impose on their programming. I guess the only
relevant part of the example was really the first comment - quote: "Dare
I say it, but this is one spot where I think the VB syntax definately
removes confusion".

My point was that the VB.Net way of doing things (which resembles how
it's done in other user-friendly programming languages, eg. Delphi) is
much less error-prone and much less frustrating for the developer.
IMHO, most developers hate doing ugly kludges like what is needed here,
because they are error-prone and because they introduce entire methods
that are just a waste of lines of code, nothing else. Giving the
developer the choice of when to call the super-class constructor (with a
default of 'first') is as clear as it can get, and C# unfortunately does
not support it.

I might not have made myself completely clear in my first posting, so
I'll try a code example. I'm pretty bad at examples, so try and keep up
:-).

Let's say I have a bunch of different components I'm developing, and for
the sake of this example, they're all implemented as background
services. They communicate over the network with a central logging
facility, a relational database, and several coffee makers. The code
that connects to these devices are pretty much the same for all the
services. Additionally, the services cannot function at all without
access to the database where their data is stored, and are (for
management purposes) not allowed to start if the logging facility is not
available.

Since the database and logging facility initialization code is shared
and needs to always run, the developer finds that it's a natural choice
to implement it in a super-class and make sure it's called in the
super-class constructor. All services derive from this class and thus
performs the initialization as the first thing.

However, in order to uniquely identify each service running on the
network, they must have a unique id. This is used to log
start/stop/whatever messages to the central logging facility.

Depending on the particular kind of service, they need to get this id
from a specific pool of id's.

For instance, federal regulation requires that all services which are
related to doing datamining for customers selling large quantities of
red wine (RedWineDataAnalyzer services) need to retrieve their unique id
from a bowl of petunias reachable over the network. The bowl of
petunias is situated in a federal institution, and designates id's that
are unique across multiple data mining institutions approved by the
government. (The reason that it's a bowl of petunias is that it was
designed by the government's military/defense wing, and they went
under-budget and needed to burn some money before the new year.)

All services related to controlling greenhouse irrigation needs to get
their id's from a pool of muddy water, also reachable over the network.

The interface to communicating with the bowl of petunias and the pool of
muddy water is of course quite different, therefore it made sense for
the developer to implement that code in the service sub-classes.

Now here is the problem: The shared code must always run, thus it is in
the constructor (of the super-class). But the (sub-class) non-shared
code which is needed to provide an interface to the id-assigning bowl of
petunias and pool of muddy water needs to be called first. How is this
done in C#, you ask? Like this, perhaps:

===========================
class Service {
protected string id = null;

private void connectToLoggingFacility() { .. use id .. }
private void logServiceStart() { .. use id .. }
private void connectoToDb() { .. use id .. }

public Service() {
connectToLoggingFacility();
logServiceStart();
connectoToDb();
}
}

class RedWineDataAnalyzerService {
private void retrieveIdFromPetunias() { .. set id .. }

public RedWineDataAnalyzerService() {
retrieveIdFromPetunias();
base();
}
}
===========================

..... no, because the base constructor is implicitly and effectively
always called first in C#.
You have to do something like this:

===========================
class Service {
protected string id = null;

private void connectToLoggingFacility() { .. use id .. }
private void logServiceStart() { .. use id .. }
private void connectoToDb() { .. use id .. }

protected virtual void retrieveIdFromWhatever() {
// blank method
}

public Service() {
retrieveIdFromWhatever();
connectToLoggingFacility();
logServiceStart();
connectoToDb();
}
}

class RedWineDataAnalyzerService {
protected override void retrieveIdFromWhatever() {
// Connect to bowl of petunias and retrieve id here.
// If you forget the 'override' keyword, you're screwed.
}

public RedWineDataAnalyzerService(): base() {
retrieveIdFromPetunias();
}
}
===========================

Let's assume that someone, long ago employed at the company in question,
implemented the super-class. Now someone else has to create a new
service which answers telephones. Looking at the first example, he
would instinctly know that during construction of the service, he needs
to first retrieve a unique ID, then to have the super-class constructor
do whatever magic it does.

Unfortunately, noone at the company documents any code, and our guy has
only the second example (using correct C# syntax) to go after. He looks
at the code for the RedWineDataAnalyzer service and copies bits and
pieces from it. He has no clue what retrieveIdFromWhatever is used for,
and he can't tell from the RedWineDataAnalyzer code when it's called,
thus he decides to leave it out. This has the effect that his telephone
answering machine services does not log to the central logging facility.
Noone immediately discovers this, but it means that management has no
idea where they are installed or when they run.

Results are that, over time, rogue telephone answering machine services
all over the company, long forgotten, from time to time kicks in and
answers telephones with product prices from a decade ago, which the
company then has to abide by, thus they eventually go bankrupt.

Conclusion:
Asides from being a kick in the groin to the developers, the C# syntax
causes bankruptcy and, through the distinction of healthy development
firms, economic recession.

The example given is perhaps a bit excessive, but I hope it proves the
point - the current limitations on syntax is counter-intuitive and
confusing to developers.
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com