calling base constructor

R

ryanbreakspear

Hi,

Is it possible to call a different base constructor (or just different
parameters) in the body of a constructor in C#?

Something like:

public class test
{
public test(bool value)
{
if (value)
base("True Value")
else
base("False Value")
}
}

Sorry if this doesn't make sense. In Delphi, you can do something
like:

constructor Create(Value :boolean);
begin
if Value then
inherited Create("True Value")
else
inherited Create("False Value);
end

I've had a look around and I don't think there is a way of doing it.
Can anyone confirm this either way.

Thanks

Ryan
 
A

Alex Meleta

Hi,

Did you mean


Regards, Alex
[TechBlog] http://devkids.blogspot.com

r> Hi,
r>
r> Is it possible to call a different base constructor (or just
r> different parameters) in the body of a constructor in C#?
r>
r> Something like:
r>
r> public class test
r> {
r> public test(bool value)
r> {
r> if (value)
r> base("True Value")
r> else
r> base("False Value")
r> }
r> }
r> Sorry if this doesn't make sense. In Delphi, you can do something
r> like:
r>
r> constructor Create(Value :boolean);
r> begin
r> if Value then
r> inherited Create("True Value")
r> else
r> inherited Create("False Value);
r> end
r> I've had a look around and I don't think there is a way of doing it.
r> Can anyone confirm this either way.
r>
r> Thanks
r>
r> Ryan
r>
 
M

Marc Gravell

Not in the body, but you can cheat - for example:

public test(bool value) : base(value ? "True Value" : "False Value") {}
or
public test(bool value) : base(Foo(value)) {}

static string Foo(bool value) {
// parse the arg(s) in a more complicated way that ternary
return "Bar";
}

Marc
 
J

Jon Skeet [C# MVP]

Is it possible to call a different base constructor (or just different
parameters) in the body of a constructor in C#?

No. The base (or "this") constructor call is always the first thing
that happens. However, you can still use parameters. For instance,
instead of this:
Something like:

public class test
{
public test(bool value)
{
if (value)
base("True Value")
else
base("False Value")
}
}

you'd have:

public test(bool value)
: base (value ? "True Value" : "False Value")
{
}

You can call methods as well, but only static ones:

public test(bool value)
: base (FormatValue(value))
{
}

static string FormatValue(bool v)
{
if (v)
{
return "True Value";
}
else
{
return "False Value";
}
}
 
A

Alex Meleta

Hi,

It's like public test(bool value) : base ([value]) { ... } (with some restrictions,
see more there http://msdn2.microsoft.com/en-us/library/ms173115.aspx)

Regards, Alex
[TechBlog] http://devkids.blogspot.com

r> Hi,
r>
r> Is it possible to call a different base constructor (or just
r> different parameters) in the body of a constructor in C#?
r>
r> Something like:
r>
r> public class test
r> {
r> public test(bool value)
r> {
r> if (value)
r> base("True Value")
r> else
r> base("False Value")
r> }
 
R

ryanbreakspear

No. The base (or "this") constructor call is always the first thing
that happens. However, you can still use parameters. For instance,
instead of this:



you'd have:

public test(bool value)
    : base (value ? "True Value" : "False Value")
{

}

You can call methods as well, but only static ones:

public test(bool value)
    : base (FormatValue(value))
{

}

static string FormatValue(bool v)
{
    if (v)
    {
         return "True Value";
    }
    else
    {
         return "False Value";
    }

}

Thanks Guys,

The ?...: syntax isn't something I've used before (and looks a bit
strange to my eyes).

I've just tried it though and it does exactly what I need.

Thanks again

Ryan
 
M

Mythran

message
Thanks Guys,

The ?...: syntax isn't something I've used before (and looks a bit
strange to my eyes).

I've just tried it though and it does exactly what I need.

Thanks again

Ryan

The ?...: is simply a short-circuited inline-if:

if (boolean-expression) {
... true reaches here ...
} else {
... false reaches here ...
}

for very simple if then else statements:

(boolean-expression) ? ... true reaches here ... : ... false reaches here
....

example:

string a = "A";
string b = "B";
string equality = (a == b ? "True" : "False");

but my example isn't the greatest...this can further be reduced to:

string a = "A";
string b = "B";
string equality = (a == b).ToString();

:p

HTH,
Mythran
 
P

Peter Morris

I once wrote to Anders H and asked why you can't call the base constructor
at any point within your body. He was kind enough to reply with a detailed
answer, unfortunately it wasn't an answer to the question I asked :) He
answered why C# doesn't have named constructors and not why you can't decide
where to call a base constructor.

I have found this a bit of a pain when the base constructor calls another
method, for example.

public class BaseClass
{
protected List<Member> Members;
public BaseClass()
{
Members = new List<Member>();
InitializeDefaultValues();
}

protected virtual void InitializeMembers()
{
foreach(Member currentMember in Members)
currentMember.Initialize();
}
}

public class ChildClass : BaseClass
{
public ChildClass() : base()
{
Members.Add(new Member("Hello");
Members.Add(new Member("Goodbye");
}
}


In this case Hello and Goodbye wont get initialized, I'd have to either
explicitly call InitializeMembers or duplicate the initialization code.


It would be nice if this changed in my opinion, but I don't suppose it will.
Anyway, I just thought I'd make you aware of it :)




Pete
 
M

Marc Gravell

I have found this a bit of a pain when the base constructor
calls another method

Well, calling a virtual method in a ctor is already risky enough - but
there are ways of getting around it. I know it is a simplified
example, but your version could easily be replaced with (for example):

BaseClass(params string[] members) {
// (creates members, and inits them)
}
ChildClass() : base("Hello", "Goodbye") {}

of course, harder for more complex objects, but in C# 3 with object
initializers it should be easy to pass full-formed objects to the base
ctor.

Alternatively (in the base)

protected void InitAndAdd(params Member[] members) {
// inits and adds members
}

that your sub-class can call, which keeps it clear what happens when

Marc
 
P

Peter Duniho

I once wrote to Anders H and asked why you can't call the base
constructor
at any point within your body. He was kind enough to reply with a
detailed
answer, unfortunately it wasn't an answer to the question I asked :) He
answered why C# doesn't have named constructors and not why you can't
decide
where to call a base constructor.

I can't speak for him or others involved in the design of C#. However, to
me it makes perfect sense that you can't call the base constructor except
at the very beginning of the derived constructor. A classic convention in
OOP is that by the time the derived class executes any code, the base
class has been completely constructed. Allowing the base constructor to
be called elsewhere would break this fundamental approach.

As far as your example goes:
I have found this a bit of a pain when the base constructor calls another
method, for example.

public class BaseClass
{
protected List<Member> Members;
public BaseClass()
{
Members = new List<Member>();
InitializeDefaultValues();
}

protected virtual void InitializeMembers()
{
foreach(Member currentMember in Members)
currentMember.Initialize();
}
}

public class ChildClass : BaseClass
{
public ChildClass() : base()
{
Members.Add(new Member("Hello");
Members.Add(new Member("Goodbye");
}
}

In this case Hello and Goodbye wont get initialized, I'd have to either
explicitly call InitializeMembers or duplicate the initialization code..

Here, the base class clearly expects the derived class to override the
initialization behavior. In that case, it seems obvious to me that the
addition of new elements to the Members field belongs in an override of
the InitializeMembers() method, given the existing design.

You don't have to duplicate anything. You just have to override the
virtual method, put your initialization in there, and then call the base
method after the initialization happens (yes, it's an explicit call to
InitializeMembers(), but it's from the override, which is a perfectly
normal and appropriate thing to do).

Frankly, the fact that in your example the InitializeMembers() method is
virtual makes a very strong suggestion that it doesn't belong in the
constructor at all, and that the class really should have a slightly
different initialization model. One in which that initialization is
handled separately from construction of the object. But even given the
exact design above, the right way to deal with initialization is obvious
and completely workable.
It would be nice if this changed in my opinion, but I don't suppose it
will.

I hope it doesn't. There are always good ways around the apparent
limitation, and IMHO the limitation makes for a robust, reliable
language. There's a reason that the limitation is present in many OOP
languages (all of the ones I know of, in fact, including C#, Java, and
C++).

Pete
 
P

Peter Morris

BaseClass(params string[] members) {
// (creates members, and inits them)
}
ChildClass() : base("Hello", "Goodbye") {}

This code was for an object persistence framework I wrote for the Pocket PC.
Having to list the members every time you create a new Person would be
inappropriate I think :)
 
P

Peter Morris

I can't speak for him or others involved in the design of C#. However, to
me it makes perfect sense that you can't call the base constructor except
at the very beginning of the derived constructor.
<<

Maybe they should have a word with the people who designed .NET then,
because in MSIL you can apparently call the base constructor at any point
you wish :)


I don't recall the exact scenario, the one below was the best I could manage
to illustrate the problem. In the past I managed to work around it but I
don't recall the problem or the solution. But it was something like my
example I *think*

Whatever the problem was I managed to solve it. It's just than coming from
Delphi I was used to being able to initialise stuff before calling a base
constructor and so I got used to it. My post was to make the original
poster aware of this "pitfall".


public abstract class BaseClass
{
public BaseClass()
{
HelloMember.Value = "Hello";
GoodbyeMember.Value = "Goodbye";
}

public abstract StringMember HelloMember { get; }
public abstract StringMember GoodbyeMember { get; }
}


public class ConcreteClass : BaseClass
{
public ConcreteClass() : base
{
HelloMember = new StringMember("Hello");
GoodbyeMember = new StringMember("Goodbye");
}

public override StringMember HelloMember { get; private set; }
public override StringMember GoodbyeMember { get; private set; }
}


This will obviously throw an NullReferenceException. It's coming back to me
now I think! In C# I would have to introduce a virtual method (which is
what I did in my solution) which creates the members


public abstract class BaseClass
{
public BaseClass()
{
CreateMembers();
HelloMember.Value = "Hello";
GoodbyeMember.Value = "Goodbye";
}

protected abstract void CreateMembers();
public abstract StringMember HelloMember { get; }
public abstract StringMember GoodbyeMember { get; }
}


public class ConcreteClass : BaseClass
{
public ConcreteClass() : base
{
}

protected override void CreateMembers()
{

HelloMember = new StringMember("Hello");
GoodbyeMember = new StringMember("Goodbye");
}

public override StringMember HelloMember { get; private set; }
public override StringMember GoodbyeMember { get; private set; }
}


Whereas by being able to call the base constructor when you choose you could
do this.


public abstract class BaseClass
{
public BaseClass()
{
HelloMember.Value = "Hello";
GoodbyeMember.Value = "Goodbye";
}

public abstract StringMember HelloMember { get; }
public abstract StringMember GoodbyeMember { get; }
}


public class ConcreteClass : BaseClass
{
public ConcreteClass()
{
HelloMember = new StringMember("Hello");
GoodbyeMember = new StringMember("Goodbye");
base();
}

public override StringMember HelloMember { get; private set; }
public override StringMember GoodbyeMember { get; private set; }
}

which is less work.

Calling a constructor would allocate memory for the class's members and the
constructor merely provides a way to initialise their values. By not being
able to choose when to call the base constructor I must add an additional
virtual method just to initialise the members.



Pete
 
P

Peter Duniho

BaseClass(params string[] members) {
// (creates members, and inits them)
}
ChildClass() : base("Hello", "Goodbye") {}

This code was for an object persistence framework I wrote for the Pocket
PC.
Having to list the members every time you create a new Person would be
inappropriate I think :)

I don't understand that comment. I don't see any real difference between
listing them explicitly in the constructor (per your original example) and
listing them explicitly in the call to the base constructor (per Marc's
example).

If your actual code is different, then sure I suppose Marc's example
wouldn't work. But that'd only be because your actual code is different
from the sample you posted. It doesn't change the validity of Marc's
suggestion given the example he had to work with. Garbage in, garbage
out. :)

Pete
 
P

Peter Duniho

I can't speak for him or others involved in the design of C#. However,
to
me it makes perfect sense that you can't call the base constructor except
at the very beginning of the derived constructor.
<<

Maybe they should have a word with the people who designed .NET then,
because in MSIL you can apparently call the base constructor at any point
you wish :)

Using assembly, I could call the base constructor at any point I wish
using C++ too. I don't see how that invalidates the idea that the
_language_ (C# or C++) should prohibit doing so.

At a lower level you can always do all sorts of things that aren't really
safe, or even approved. That doesn't mean it's a good thing to do.
[...]
Calling a constructor would allocate memory for the class's members and
the
constructor merely provides a way to initialise their values. By not
being
able to choose when to call the base constructor I must add an additional
virtual method just to initialise the members.

I don't see how that's a bad thing. It makes it a lot more clear in your
code that you're doing something unconventional. As I mentioned, I really
think that these sorts of things are better handled with a different
initialization model anyway. But inasmuch as you insist on performing the
initialization in the constructor, I think it's perfectly reasonable for
the language designers to make a choice to require that sort of behavior
to be more explicit.

I gather from your post that Delphi doesn't have this same restriction.
However, I have to say that for me, that doesn't impress me as any sort of
justification or argument in favor of allowing it in another language.
I've seen other examples of people coming from Delphi and being confused
or frustrated by C#'s relative rigidity. One guy who used to ask for help
here had no real understanding of recursion, because he was used to
iterating through a recursive data structure in Delphi, which apparently
hid the recursion from him (it exposed the collection as a linear list).

If anything, these things just reinforce my feeling that, assuming what
people say about Delphi is true, that Delphi is not a very good OOP
language.

By the way, I take back what I wrote about all OOP languages I know having
this restriction. You've already mentioned Delphi and while I didn't know
it didn't have this restriction, I already knew of another language that
also doesn't. Objective-C is similarly "flexible" in its rule about
construction. But again, I find this to be a bad thing...along with the
fact that in Objective-C it's possible to have an object that has _never_
been fully initialized (derived classes inherit base class constructors,
which can lead to allocation of an instance of a class without ever
calling the constructor for that class or any class in the hierarchy
between the actual class and the constructor you actually called...ugh!),
this kind of flexibility just leads to weird, hard-to-figure-out bugs.

Pete
 
P

Peter Morris

Using assembly, I could call the base constructor at any point I wish
using C++ too. I don't see how that invalidates the idea that the
_language_ (C# or C++) should prohibit doing so.

MSIL isn't assembly. My point was that it is valid in .NET, and .NET
protects you from a lot of "dodgy" practises.

I don't see how that's a bad thing. It makes it a lot more clear in your
code that you're doing something unconventional. As I mentioned, I really
think that these sorts of things are better handled with a different
initialization model anyway. But inasmuch as you insist on performing the
initialization in the constructor,

No, that's inaccurate. It is fair to say "I originally put my creation in
the constructor". I thought it was pretty clear that I changed it to create
the members in CreateMembers(), hence the name.

I gather from your post that Delphi doesn't have this same restriction.
No.


However, I have to say that for me, that doesn't impress me as any sort of
justification or argument in favor of allowing it in another language.

I didn't argue that it should be allowed because it is in Delphi. I argued
that it is perfectly valid in .NET, and that I was used to it because I came
from Delphi.


I've seen other examples of people coming from Delphi and being confused
or frustrated by C#'s relative rigidity. One guy who used to ask for help
here had no real understanding of recursion,

Then I would argue he was a beginner, or crap.

because he was used to iterating through a recursive data structure in
Delphi, which apparently hid the recursion from him (it exposed the
collection as a linear list).

This is no different to .NET presenting a tree structure in a linear way
using an IEnumerable. The fact is that Delphi doesn't "hide" recursion from
the programmer, many Delphi programs use recursion, for example to find all
files in a directory structure. Your assumption is incorrect and based on a
single case.

If anything, these things just reinforce my feeling that, assuming what
people say about Delphi is true, that Delphi is not a very good OOP
language.

Again I would argue that you are incorrect. Delphi is very similar to C#
which is why I found C# so easy to pick up. In my experience many Delphi
programmers think in a procedural way and merely write methods in events,
but I have not experience much difference in C# either to be honest. My
point is, you can't judge a language by its users.

By the way, I take back what I wrote about all OOP languages I know having
this restriction. You've already mentioned Delphi and while I didn't know
it didn't have this restriction, I already knew of another language that
also doesn't. Objective-C is similarly "flexible" in its rule about
construction

There is also Chrome from www.RemObjects.com, I believe this allows you to
call the constructor at any point you wish.

But again, I find this to be a bad thing

If everyone in the world shared the same opinions it would be a truely dull
place to live :)

fact that in Objective-C it's possible to have an object that has _never_
been fully initialized (derived classes inherit base class constructors,
which can lead to allocation of an instance of a class without ever
calling the constructor for that class or any class in the hierarchy
between the actual class and the constructor you actually called...ugh!),
this kind of flexibility just leads to weird, hard-to-figure-out bugs.

It's perfectlly possible in C# to introduce bugs that do not initialise all
of your members properly, for example

public class MyClass
{
protected int? SomeValue;
protected string Name;

public MyClass(int value)
{
SomeValue = value;
}


public MyClass(int value, string name)
// : this(value)
{
Name = name;
}
}

In this example the developer has forgotten the call to this(value). This
is an equivalent scenario to not calling a base constructor, you end up with
a partially initialised object. Every language allows the developer to
write bugs in one way or another, it's up to the developer to have good
practises to try to avoid them as much as possible and ensure they are not
released.

Here is another example of a bug:

class Program
{
static void RecordChangedValue(object newValue)
{
object oldValue = 1;
if (newValue != oldValue)
throw new ArgumentNullException("Value seems to have changed");
}

static void Main(string[] args)
{
RecordChangedValue(1);
}
}

I encountered something like this when implementing in-memory
transaction/rollback on my OPF. When a member is modified within a
transaction its original value is stored as a System.Object, so everything
is compared as System.Object, but in this case 1 does not equal 1 because
the default implementation for object comparision is ByRef and not ByValue.

That's a behaviour specific to .NET. I am aware of it so I avoid it when I
write code.


Pete
 
P

Peter Morris

I don't understand that comment. I don't see any real difference between
listing them explicitly in the constructor (per your original example) and
listing them explicitly in the call to the base constructor (per Marc's
example).

Oh I see, I misunderstood. I thought you were suggesting

Person p = new Person("FirstName", "LastName", etc etc)


I still don't think that's a good approach anyway, because when you get
inheritance of business classes it gets messy


public class Product : PersistentObject......
public class Software : Product.....
public class Collateral : Product....

You'd need two constructors on each class. One for "normal" use, and one
for creating the members which is called from the parameterless
constructor.....

new Collateral();
->Calls parameterless constructor
->Calls this(member list)

Now which constructor would it call on Product? Calling the one with
parameters would bypass the one without parameters, calling the one without
parameters would mean that the Product class would be unaware of the
parameters from Collateral.
Garbage in, garbage out. :)

I agree, but in this case I think this is an example of garbage in :)

My solution was to have a virtual CreateMembers method on PersistentObject
which is called from the constructor and all classes should create their
members from there. As I said, I worked around it, but I wanted this Delphi
guy to realise the pitfalls of calling virtual methods when he has no
control over when the base constructor is called.



Pete
 
P

Peter Duniho

[...]
It's perfectlly possible in C# to introduce bugs that do not initialise
all
of your members properly,

I'm not talking about lack of "proper" initialization. I'm talking about
lack of initialization period.

In the C# example you posted, _a_ constructor gets called for every class
in the inheritance hierarchy. You may have a bug in which the wrong one
is called, but there's always one that gets called. In Objective-C, it is
possible for a constructor for one or more classes in the hierarchy to
simply not be called at all.

Anyway, it sounds like Delphi was unfairly represented by the other
person. I still stand by my opinion that it's a good thing to require
base constructors to have all finished executing before any derived
constructor gets to execute.

Pete
 
T

Thana at Thailand

I faced this problem in my work.

I designed custom Exception that has custom fields ex:
- severity ex. "E" - error, "W" - warning
- ErrCode ex. "001","002",...

then I want to create a constructor that get input from string
ex: "E,001,Error Message" ( the real format is slightly different and
it is the standard error code and message of my mainframe host apps)

then my Exception will contain fields :

- severity = "E"
- errCode = "001"
- Message = "Error Message" ( this field need to pass to
System.Exception constructor )

class MyException : Exception
{
// fullMsg ex. "E,001,Error Message"
MyException(string fullMsg) : base( cutMsg(fullMsg) )
{
severity = ... (ex. "E")
errCode = ... (ex. "001")
}

private static string cutMsg(string fullMsg)
{
return ... (ex. "ErrorMessage")
}
}

This is quite not straightforward.
because in cutMsg() method, I can split string and get all fields ( E ,
001, Error Message ) but I can return only "Error Message" to init at
base constructor

and then I need to re-split message again to get "E" and "001" at body
of constructor.

I think that currently C# don't have neat syntax to solve this problem.
To solve this neatly, it is needed to introduce 'calling base
constructor in the body of child constructor' syntax. As in VB.Net and
Java can.

I love C# but find this flaw quite borther me.
So, do I need to accept doing it in indirect way?

ps. This way, if constructor has 3 arguments, then you need to create 3
static method (ex. cutMsg() ) for parse each argument.

- : Exception(cutMsg1(), cutMsg2(), cutMsg3())

quite redundant

Very appriciate, if anyone have any suggestions.
Thanks.
 
P

Peter Duniho

[...]
then my Exception will contain fields :

- severity = "E"
- errCode = "001"
- Message = "Error Message" ( this field need to pass to
System.Exception constructor )

If your exception class has three fields, why doesn't the constructor have
three parameters, one for each field?

For example:

class MyException : Exception
{
public MyException(string severity, string errCode, string message)
: base(message)
{
this.severity = severity;
this.errCode = errCode;
}
}

I also don't see what's so terrible about this example you posted:
class MyException : Exception
{
// fullMsg ex. "E,001,Error Message"
MyException(string fullMsg) : base( cutMsg(fullMsg) )
{
severity = ... (ex. "E")
errCode = ... (ex. "001")
}

private static string cutMsg(string fullMsg)
{
return ... (ex. "ErrorMessage")
}
}

I wouldn't use it unless for some reason there was some really compelling
reason that forced you to have the constructor take just a single string
as a parameter _and_ you also for some reason were forced _not_ to be able
to have a separate method create the instance for you, as in:

class MyException : Exception
{
public MyException(string severity, string errCode, string message)
: base(message)
{
this.severity = severity;
this.errCode = errCode;
}

public static MyException FromFullMessage(string fullMsg)
{
// split string here, then...
return new MyException(severity, errCode, message);
}
}

But any of these alternatives seem reasonable to me, even if I like your
version the least.
This is quite not straightforward.
because in cutMsg() method, I can split string and get all fields ( E ,
001, Error Message ) but I can return only "Error Message" to init at
base constructor

and then I need to re-split message again to get "E" and "001" at body
of constructor.

Sounds like a great argument for passing each part of the string
individually in the first place, or for using a static "From..." method.
I think that currently C# don't have neat syntax to solve this problem..
To solve this neatly, it is needed to introduce 'calling base
constructor in the body of child constructor' syntax. As in VB.Net and
Java can.

I can't speak for VB.NET. Though, given the other things VB.NET does that
I don't like, it wouldn't surprise me. But in Java, while you do call
"super()" from inside the constructor, you don't get to execute any code
before it. It has to be the first thing. It's not really any different
from C# or C++ in practice.
I love C# but find this flaw quite borther me.
So, do I need to accept doing it in indirect way?

I disagree that it's a flaw. But yes, whether you think it's a flaw or
not, that's how the language is. You must "accept doing it in indirect
way".

I've yet to see an example of where this particular design choice forces
some completely inappropriate alternative on a person. Yes, the code
sometimes needs to be different. But it never has to be bad.
ps. This way, if constructor has 3 arguments, then you need to create 3
static method (ex. cutMsg() ) for parse each argument.

- : Exception(cutMsg1(), cutMsg2(), cutMsg3())

quite redundant

Honestly, when you start getting into something like that, I personally
think that the language is giving you a nice big hint that there's
something awkward about your design. A constructor that takes three
strings, each of which needs to be parsed so that some portion of the
string can then be passed to the base class, that's just asking to be
redesigned into something simpler and easier to use.

But in any case, you can always have a separate method to handle the
preprocessing _and_ instantiation, if you find that you don't like
hammering the constructor base-calling syntax into your existing design.

Pete
 
P

Peter Morris

I'm not talking about lack of "proper" initialization. I'm talking about
lack of initialization period.

Delphi doesn't do that. The first constructor that is executed will create
all of the required memory etc for the whole hierarchy, the constructor code
is initialisation only.

I still stand by my opinion that it's a good thing to require base
constructors to have all finished executing before any derived
constructor gets to execute.

And although I have a work around and do not struggle with the current
implementation I expect I will stand by my opinion too :)



Pete
 

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