Inheritance of constructors.

A

A n g l e r

Hi all.

I'm facing the following construction:

class ClOld
{
public ClOld(string a) { ... }
}

class ClNew: ClOld
{
SomeData[] arr;
public ClNew(string a, SomeObject b): base(a)
{
arr = new SomeData[] {b.data1, b.data2, b.data3 };
}
}

Now, I wonder how to pass initialized arr to a base constructor. Why
can't I code something like below:

class ClOld
{
public ClOld(string a, ref SomeData[] arr) { ... }
}

class ClNew: ClOld
{
SomeData[] arr;
public ClNew(string a, SomeObject b):
{
arr = new SomeData[] {b.data1, b.data2, b.data3 };
base(a, ref arr);
}
}


Thanks in advance,
Pete
 
J

Jon Skeet [C# MVP]

I'm facing the following construction:

Now, I wonder how to pass initialized arr to a base constructor. Why
can't I code something like below:

<snip>

Basically you can't write any actual code in the constructor before
the base constructor call. You *can* make a static method call, so you
can do:

public ClNew(string a) : base(a, CreateArray())
{
// Other stuff
}

That won't help you for a ref parameter, however. Are you sure you
need a ref parameter in the constructor call? That's pretty unusual.

Jon
 
A

A n g l e r

Basically you can't write any actual code in the constructor before
the base constructor call. You *can* make a static method call, so you
can do:

Brilliant, I thought so. Blooming drawbacks of the garbage collector and
the whole automated memory management by ms, right? :/
public ClNew(string a) : base(a, CreateArray())
{
// Other stuff
}

That will help for now :)
That won't help you for a ref parameter, however. Are you sure you
need a ref parameter in the constructor call? That's pretty unusual.

No, I guess I don't cos I pass just an array of objects which anyway
means (I guess so) it's handled in a similar way to reference. Isn't it?

DataGridView[] arr = new DataGridView[] { grid1, grid2, grid3 };

Cheers,
P.
 
J

Jon Skeet [C# MVP]

Brilliant, I thought so. Blooming drawbacks of the garbage collector and
the whole automated memory management by ms, right? :/

Well, it's more that doing things within an object before it's been
initialized in the parent is somewhat questionable.

That won't help you for a ref parameter, however. Are you sure you
need a ref parameter in the constructor call? That's pretty unusual.

No, I guess I don't cos I pass just an array of objects which anyway
means (I guess so) it's handled in a similar way to reference. Isn't it?

DataGridView[] arr = new DataGridView[] { grid1, grid2, grid3 };

There's a big difference between "pass by reference" and "pass
reference by value". It confuses quite a lot of people, and it's well
worth being aware of the difference. It's mostly down to confusingly
named terminology, IMO.

See http://pobox.com/~skeet/csharp/parameters.html

Jon
 
A

A n g l e r

Well, it's more that doing things within an object before it's been
initialized in the parent is somewhat questionable.

Consider an example where a new class (for instance it's constructor) is
in charge of the data preparation which is fed to a parent class
constructor. OK, you can pass it via static variable as suggested,
though what happens if you want to have different data in it for each
instance of a new class? Unless static in C# means it exists over the
whole cycle of a code execution but doesn't limit it to one global data
copy shared amongst all instances like in C++. Is this the case?
There's a big difference between "pass by reference" and "pass
reference by value". It confuses quite a lot of people, and it's well
worth being aware of the difference. It's mostly down to confusingly
named terminology, IMO.

See http://pobox.com/~skeet/csharp/parameters.html

Sure, it's just all happens on different levels. The actual reference is
all about where it is in the memory. The value reference is more like a
container that is being copied while passing.

Thanks,
P.
 
A

A n g l e r

Consider an example where a new class (for instance it's constructor) is
in charge of the data preparation which is fed to a parent class
constructor. OK, you can pass it via static variable as suggested,
though what happens if you want to have different data in it for each
instance of a new class? Unless static in C# means it exists over the
whole cycle of a code execution but doesn't limit it to one global data
copy shared amongst all instances like in C++. Is this the case?

Erm, OK, I see what happens in this case. It's passed via static method,
the value reference is stored locally in a base class. No harm done
unless I would prefer it would be capable of following every change of
the value reference in outer classes ... what then?
 
J

Jon Skeet [C# MVP]

Consider an example where a new class (for instance it's constructor) is
in charge of the data preparation which is fed to a parent class
constructor. OK, you can pass it via static variable as suggested,
though what happens if you want to have different data in it for each
instance of a new class? Unless static in C# means it exists over the
whole cycle of a code execution but doesn't limit it to one global data
copy shared amongst all instances like in C++. Is this the case?

I didn't suggest a static *variable*. I suggested a static *method*.
The method should be able to construct the information required for
the base class's constructor which no information about the current
(uninitialized) instance.
Sure, it's just all happens on different levels. The actual reference is
all about where it is in the memory. The value reference is more like a
container that is being copied while passing.

Not sure what you mean by "value reference" but the point is that
there's a big difference between
void Foo(ref object[] x)
and
void Foo(object[] x)
even though object[] is a reference type. I rarely see a genuine need
for the former signature.

Jon
 
J

Jon Skeet [C# MVP]

Erm, OK, I see what happens in this case. It's passed via static method,
the value reference is stored locally in a base class. No harm done
unless I would prefer it would be capable of following every change of
the value reference in outer classes ... what then?

I don't really understand what you mean by the last sentence. Could
you give a concrete example in code of what you'd like to be able to
do?

Jon
 
A

A n g l e r

I don't really understand what you mean by the last sentence. Could
you give a concrete example in code of what you'd like to be able to
do?

Ok, here it goes:

class ClOld
{
public SomeData[] arr;
public ClOld(string a, SomeData[] b) { arr=b; }
}

class ClNew: ClOld
{
static SomeData[] arr;
static SomeData[] StaticPassing(SomeClass src)
{
arr = new SomeData[] { src.d1, src.d2, src.d3 };
return arr;
}

public void UpdateArr(src)
{
arr = new SomeData[] { src.d1, src.d2, src.d3 };
// the arr is now assigned a new reference by value
// though, this doesn't mean that base.arr is also updated
// with a new reference value unless
// I'll update it on myself, for instance base.arr=arr; or more
//likely by set, get that act on arr while it remains the
// private member of ClOld

//also, if I made the arr public in thr ClNew and modified its
//reference by value from outside of the ClNew class, I'd have
//to handle some further updating actions which is inconvenient
}

public ClNew(string a, SomeObject b): base(a, StaticCopier())
{
}
}

ClNew aa= new ClNew(src);
aa.arr=new SomeData[] { data }

// aa.base.arr stays unchanged unless I'll update it. In case of memory
// references it wouldn't be any concern as long as all this happens in
// one thread
 
A

A n g l e r

Not sure what you mean by "value reference" but the point is that

Sorry, I mean reference by value which indicates that the reference is
copied and isn't maintained automatically by another instances of the
actual "reference by value" container :d

class1 aa=new class1("d1");
bb=aa;
aa= new class1("d2");

bb still contains d1
aa contains d2

while in case of memory-wise C++ reference
bb would contain d2
aa would contain also d2

Therefore I said that reference by value is like a container of
reference. It helps you avoid copying of the whole objects, but you have
to maintain on your own the actual copies of the references ...
 
J

Jon Skeet [C# MVP]

// aa.base.arr stays unchanged unless I'll update it. In case of memory
// references it wouldn't be any concern as long as all this happens in
// one thread

Your example is made somewhat trickier by the fact that one variable
is static, the other isn't, but they both have the same name. Avoiding
making fields public helps too :) I'm also not sure where threading
comes into it particularly...

But yes, your point that the field is a just reference rather than
something which automatically keeps track of a different variable is
correct. I can't remember when I've ever wanted the latter behaviour
though.

Jon
 
A

A n g l e r

Avoiding
making fields public helps too :)

Bare in mind that was just for sake of example.
I'm also not sure where threading
comes into it particularly...

It just comes in the sense that you wouldn't like your data collection
being modified while reading. In case of "reference by value" that's not
a problem cos it never gets updated anyway - just remains stuck with an
old collection unless you do something on your own, lol.
But yes, your point that the field is a just reference rather than
something which automatically keeps track of a different variable is
correct. I can't remember when I've ever wanted the latter behaviour
though.

Imagine a class which handles rendering at 15 frames a second. Now,
imagine that you have a collection of objects it renders to screen or
wherever you fancy. Do you really desire to inform the class that some
objects are added/removed from the data collection? I'd rather have a
memory-wise reference that assures the class would always see the
updated collection. What's the point in copying reference values of
let's say 1000 objects 15 times a second (provided collection changes so
dynamically)?

Cheers
 
J

Jon Skeet [C# MVP]

 > Avoiding


Bare in mind that was just for sake of example.

Unfortunately the duplication of variable names made it hard for me to
see what you actually meant :(
It just comes in the sense that you wouldn't like your data collection
being modified while reading. In case of "reference by value" that's not
a problem cos it never gets updated anyway - just remains stuck with an
old collection unless you do something on your own, lol.

No, the collection itself can be changed without changing which
collection the variable refers to.
Imagine a class which handles rendering at 15 frames a second. Now,
imagine that you have a collection of objects it renders to screen or
wherever you fancy. Do you really desire to inform the class that some
objects are added/removed from the data collection? I'd rather have a
memory-wise reference that assures the class would always see the
updated collection. What's the point in copying reference values of
let's say 1000 objects 15 times a second (provided collection changes so
dynamically)?

Um, you will. You can change the contents of the array or another
collection. Here's a short example:

using System;

class Foo
{
string[] names;

public Foo(string[] names)
{
this.names = names;
}

public void ShowNames()
{
Console.WriteLine("Names:");
foreach (string name in names)
{
Console.WriteLine(name);
}
}
}

class Test
{
static void Main()
{
string[] x = {"Jon", "Holly"};
Foo foo = new Foo(x);
foo.ShowNames();
x[0] = "Robin";
x[1] = "William";
foo.ShowNames();
}
}

The changes (made in Test) to the array are visible in Foo, because
they both share a reference to the same array. The same would be true
for other reference types such as List<T>.

Now in the display updating example you'd need to potentially be
careful with threading, yes - but it's not too bad a problem.

Given how the above works, why would I want to use "ref" in the
constructor signature? Bear in mind that the "ref" would only affect
the parameter itself anyway...

Jon
 
A

A n g l e r

class Test
{
static void Main()
{
string[] x = {"Jon", "Holly"};
Foo foo = new Foo(x);
foo.ShowNames();
x[0] = "Robin";
x[1] = "William";
foo.ShowNames();
}
}

And what now happens if you wanted to add yet another field? You'd have
to write x = {"bla", "bla", "bla"} which results in a new reference by
value that isn't passed to Foo. OK, you may go for some more advanced
container of objects where you can add/delete all stuff by appropriate
methods, though this suddenly becomes more and more elaborate while with
means of memory-wise reference you could replace the whole array easily
if needed.
 
J

Jon Skeet [C# MVP]

A n g l e r said:
class Test
{
static void Main()
{
string[] x = {"Jon", "Holly"};
Foo foo = new Foo(x);
foo.ShowNames();
x[0] = "Robin";
x[1] = "William";
foo.ShowNames();
}
}

And what now happens if you wanted to add yet another field?

You can't with an array. You could with other collections such as
List said:
You'd have to write x = {"bla", "bla", "bla"} which results in a new
reference by value that isn't passed to Foo. OK, you may go for some
more advanced container of objects where you can add/delete all stuff
by appropriate methods, though this suddenly becomes more and more
elaborate while with means of memory-wise reference you could replace
the whole array easily if needed.

Using List<T> is hardly elaborate, and it results in a nice simple
model. The complexity is hidden in the container, instead of having to
keep track of where a reference originally came from (and making sure
that's not inappropriately on a stack somewhere, ready to pop out of
existence...)
 
A

A n g l e r

You can't with an array. You could with other collections such as

Yeah, I know, am just being fussy cos I like fiddling with all these
properties and above all worship C++ syntax, also I do mix very often
unmanaged code with managed one and all this repacking of more complex
structures is just a waste of a processor time. Tough ...
 
A

Arne Vajhøj

Brilliant, I thought so. Blooming drawbacks of the garbage collector and
the whole automated memory management by ms, right? :/

The syntax is almost the same in C++. So no relation to GC.

Arne
 
A

A n g l e r

Arne, hi.

Thanks for the comment. I've just realised that you're actually right.
I've got a little bit hazy on details and now am rather sure that the
sort of the construction I'm referring to was available in Delphi
(perhaps C++ builder as well - don't remember now).

Cheers,
Pete
 
W

Weeble

A said:
Consider an example where a new class (for instance it's constructor) is
in charge of the data preparation which is fed to a parent class
constructor. OK, you can pass it via static variable as suggested,
though what happens if you want to have different data in it for each
instance of a new class? Unless static in C# means it exists over the
whole cycle of a code execution but doesn't limit it to one global data
copy shared amongst all instances like in C++. Is this the case?

I'll admit to being quite confused by your examples, so this may well
be completely unrelated to what you're looking for, but I thought I'd
mention it in the off-chance that it's relevant.

I have sometimes encountered the problem of wanting to do some sort of
calculation in a sub-class constructor before calling the base-class.
As Jon Skeet mentions, sometimes a static method will help you out
here, but this is not a lot of help if you have to pass several
arguments to the base class constructor that are interdependent.
Here's a way you can do that:

public class Base
{
public Base(int a, int b, int c) { /* ... */ }
}
public class Derived : Base
{
public Derived(int x, int y)
:this(new BaseArgs(x,y))
{ }
private Derived(BaseArgs args)
:base(args.a, args.b, args.c)
{ /* ... */ }
private class BaseArgs
{
public int a;
public int b;
public int c;
public BaseArgs(int x, int y)
{
int temp = ComplicatedCalculation(x,y);
a = x + temp;
b = y + temp;
c = temp * temp;
}
}
}

The idea is that you have two constructors for your base class: a
public one and a private one. The public one constructs a special
object and passes it to the private one. The private one extracts data
from that special object and passes it up to the base class. In the
constructor for the special object, you can do whatever it is that you
wanted to do before the base constructor gets called.
 
B

Ben Voigt [C++ MVP]

A said:
Arne, hi.

Thanks for the comment. I've just realised that you're actually right.
I've got a little bit hazy on details and now am rather sure that the
sort of the construction I'm referring to was available in Delphi
(perhaps C++ builder as well - don't remember now).

In Java, the call to the base constructor doesn't have to be first.

In C++ it definitely does, I don't see how Borland or Microsoft compiler
would make any difference.
 

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