Constructor chaining in C# vs. Java

G

Guest

I have just come across a real life example in which the C# syntax for
calling constructors from within other constructors is rather inconvenient.
Imagine a class with a default constructor and another constructor that takes
a parameter:

class MyClass
{
public MyClass()
{
}

public MyClass(int a)
{
}
}

In cases like these, the default constructor will usually call the other
constructor with a default value for the missing parameter, e.g.:

class MyClass
{
public MyClass() : this(100)
{
}

...
}

However, what happens if the default value of that parameter has to be
computed in a more complex way? In Java, it is as simple as doing your
calculations and then calling the second constructor:

public MyClass()
{
int b;
// do some calculations here
this(b);
}

After a lot of fiddling around, I figured out you can do something like this
in C# by implementing a static method and calling it during the constructor
chaining:

class MyClass
{
static int CalculateDefault()
{
int b;
// do some calculations
return b;
}

public MyClass(): this(CalculateDefault())
{
}

public MyClass(int a)
{
...
}
}

Needless to say, the elegance and readibility of this roundabout solution is
debatable, especially when you have more than one parameter without a
constant default value. Is there any reason why C# was designed this way?

Regards,

Daniel
 
G

Guest

I think the constructors are designed like this to keep all the C++
programmers happy rather than due to any real constraints.

I agree the Java way is better, but would say IHMO the Delphi way of
chaining constructors is better still.
 
J

John Davison

Daniel said:
However, what happens if the default value of that parameter has to be
computed in a more complex way? In Java, it is as simple as doing your
calculations and then calling the second constructor:

public MyClass()
{
int b;
// do some calculations here
this(b);
}

Bzzzt. Syntax error. If you want to call this(b), it has to be the
first line of your constructor.

If the default value has to be computed in a more complex way, then
maybe you should use factory methods, like

public static MyClass createMyClass() { }
public static MyClass createMyClass(int x) { }

You see that alot in both .NET and JFC.

John Davison
 
J

Jon Skeet [C# MVP]

Daniel Benito said:
I have just come across a real life example in which the C# syntax for
calling constructors from within other constructors is rather inconvenient.
Imagine a class with a default constructor and another constructor that takes
a parameter:

However, what happens if the default value of that parameter has to be
computed in a more complex way? In Java, it is as simple as doing your
calculations and then calling the second constructor:

public MyClass()
{
int b;
// do some calculations here
this(b);
}

Apart from the way you can't actually do that in Java either...

The answer is the same for both C# and Java. The main difference
between C# and Java constructors is that in C# the instance
initializers are run before the base constructor is called; in Java
they're called afterwards. (This usually only makes a difference if the
base constructor calls a virtual method, which is basically a bad
idea.)
 
H

Helge Jensen

Daniel said:
After a lot of fiddling around, I figured out you can do something like this
in C# by implementing a static method and calling it during the constructor
chaining:

This is the usual way you do the same in C++ and JAVA.

I tend not to overload constructors, but make the constructor the
"canonical" way of constructing instances and then provide static
methods that allow convinient related construction. This method allows
you to state how translation to the canonical construction occurs. The
shining (simplified) example is:

public class Foo {
int x;
public Foo(int x) { this.x = x; }
public Foo FromDefault() { return new Foo(...); }
public Foo FromHexString(string s) { return new Foo(int.Parse(s,
NumberStyles.Hex)); }
public Foo FromDecString(string s) { return new Foo(int.Parse(s)); }
}
 
H

Helge Jensen

Helge said:
shining (simplified) example is:

With appropriate "static"'s :)
public class Foo {
int x;
public Foo(int x) { this.x = x; }
public Foo FromDefault() { return new Foo(...); }
public static Foo FromDefault() { return new Foo(...); }
public Foo FromHexString(string s) { return new Foo(int.Parse(s,
NumberStyles.Hex)); }
public static Foo FromHexString(string s) { return new Foo(int.Parse(s,
NumberStyles.Hex)); }
public Foo FromDecString(string s) { return new Foo(int.Parse(s)); }
public static Foo FromDecString(string s) { return new Foo(int.Parse(s)); }
 
G

Guest

This usually only makes a difference if the base constructor calls a
virtual method, which is basically a bad idea.

Why is it a bad idea to call virtual methods from a constructor? Other
than the fact that instance variables may not have been initialised
(having said that, this is the case for any method, there's no
guarantee that any instance variable has been initialised).

I'm talking in a general abstract way here, I know the implementation
reasons why this can't be done. But if we had the "ideal langauge" is
there a reason why this is a bad idea?

FWIW Delphi does allow you to call virtual methods from a constructor
and I have found this to be a very useful facility in the past.
 
J

Jon Skeet [C# MVP]

Why is it a bad idea to call virtual methods from a constructor? Other
than the fact that instance variables may not have been initialised
(having said that, this is the case for any method, there's no
guarantee that any instance variable has been initialised).

If you execute a normal method, at least the variable initialisers
won't have been run, even if the rest of the constructor hasn't.
I'm talking in a general abstract way here, I know the implementation
reasons why this can't be done. But if we had the "ideal langauge" is
there a reason why this is a bad idea?

Unless the base constructor very specifically specifies that it will
call the virtual method, it could be a great surprise to the developer
of the derived class - if he isn't calling the method in his
constructor, he may well have written it assuming that by the time it's
called, the object has been fully constructed.

During construction, an object can often be in a somewhat inconsistent
state, as things are being set up. Assuming that normal method calls
will work as normal in such a situation is a bad idea.
FWIW Delphi does allow you to call virtual methods from a constructor
and I have found this to be a very useful facility in the past.

Both Java and C# *allow* you to - it's just it can easily cause
problems.
 
J

Jeff Currier

Why can't one simply use the base keyword rather then the
this keyword for this? An example...

class Employee
{
public Employee()
{
.....
}
}

class Manager
{
public Manager() : base()
{
....
}
}

I've just tried this and it works fine... Is there something I'm
missing here in the discussion?
 
J

Jon Skeet [C# MVP]

Jeff Currier said:
Why can't one simply use the base keyword rather then the
this keyword for this? An example...

base() is equivalent to super() - this() is used in both Java and C#.
class Employee
{
public Employee()
{
.....
}
}

class Manager
{
public Manager() : base()
{
....
}
}

I've just tried this and it works fine... Is there something I'm
missing here in the discussion?

Yup - the problem is that the OP wants to do some calculation within
his constructor before calling the base constructor. You can't do that
(simply) in either Java or C#.
 

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