(Re): Which constructor is used when instantiating an array of objs ?

D

david

Well, as a matter of fact I_HAD_MISSED a basic thing or two, anyway,
although Ollie's answer makes perfectly sense when dealing with
classes, it doesn't seem to me to apply as well if you have to
instantiate an array of structures; consider the following useless
code :


using System;

struct MyPointS
{
internal int x;
internal int y;
internal static int a=-1;

static MyPointS()
{ Console.WriteLine("static constr."); }

public MyPointS(int t)
{ Console.WriteLine("1 args constr."); x=y=t; }
}

public class David
{
public static void Main()
{
int ss=MyPointS.a;
// causes static constructor to run

MyPointS s1=new MyPointS();
// causes implicit default 0 args constructor to run

MyPointS s2=new MyPointS(11);
// causes 1 args constructor to run

MyPointS[] vs=new MyPointS[5];
// no explicit constructor seems to run.
// With structures (as opposed to classes) instances
// in the array DO_GET_ALLOCATED
// (on the stack, as opposed to heap),
// so that you can do the following :

vs[3].x=vs[3].y=123;
// if MyPointS weren't a structure, but a class,
// this line would cause an exception to be raised
}
}

So the basic question is the same :

"How can I instantiate an array of objects (out of a struct),
specifying - as I do when creating single objects - which constructor
should be run, to let, for instance, the array elements (or anythinhg
else) being initialized the way I want ?"

Ollie's previous answer for classes, adapted to structures

MyPointS[] vs=new MyPointS[5];
vs[3]=new MyPointS(11);

seems to suggest that, to achieve that, you happen to instantiate
twice a given object :


When you declare the array object

MyPointS[] vs=new MyPointS[5];
// five structure objs get "physically" allocated on the stack


And when you explicitely call a costructor for a given array element

vs[3]=new MyPointS(11);
// a new vs[3] obj overwrites the one previously
// created when the array was first allocated


So, it seems "anti-economical" to me having to re-create the same
object (out of a structure definition), if you just want to have it
properly initialized.

Sorry to return again on such a basic trivial topic, but I'd like to
understand if that's a (minor) flaw of the language, or, more likely,
something basic I still can't catch.


Thanks, David

MyPointC[] vc=new MyPointC[5];

does not allocate any instances in the array, it only cretaes the
System.Array object so therefore none of the MyPointC constructors are
called.

you would have to do:

MyPointC[] vc=new MyPointC[5];
vc[0] = new MyPointC();
vc[1] = new MyPointC(11);
vc[1] = new MyPointC(22222);

HTH

Ollie Riches



david said:
I have a question (not sure if just a newbie one, or a stupid one)
whose answer I couldn't find on the C# books and tutorials I could put
my hands on.

Consider the following useless class (could be a struct as well, if
you just comment out the non static parameterless constructor) and the
Main() routine :

using System;

class MyPointC
{
int x;
int y;
internal static int a=-1;

static MyPointC()
{ Console.WriteLine("static constr."); }

public MyPointC()
{ Console.WriteLine("0 args constr."); x=1; y=2;}

public MyPointC(int t)
{ Console.WriteLine("1 args constr."); x=y=t; }
}

public class David
{

public static void Main()
{
int cc=MyPointC.a;
// causes static constructor to run

MyPointC c1=new MyPointC();
// causes 0 args constructor to run

MyPointC c2=new MyPointC(11);
// causes 1 args constructor to run

MyPointC[] vc=new MyPointC[5];
// no explicit constructor seems to run
}
}

The question is :
"How can I instantiate an array of objects (both from a class or a
struct), specifying - as I do when creating single objects - which
constructor should be run, to let, for instance, the array elements
(or anythinhg else) being initialized the way I want ?"


MyPointC[] vc=new MyPointC()[5];
or
MyPointC[] vc=new MyPointC[5]();

are both invalid syntax, rejected by the compiler.


Am I missing a basic thing or two ?!?


Thanks, David
 
G

Guest

Arrays are reference types and are allocated on the managed heap, not on the
stack. It does not matter what the element type is: reference type or value
type - the array is still on the heap.

An array of a struct type (i.e. a value type) will have each element
initialized to the default value for that type. The language spec defines it
this way:

"the default value of a struct is the value produced by setting all value
type fields to their default value and all reference type fields to null."
(Section 11.3.4 even shows an example of an array.)

You can think of it as if the "default constructor" is run for each element
of the array. Remember though, for a struct, you cannot write the default
constructor, the compiler always writes it for you so you will not be able to
put a print statement inside to see it called.
 
R

Richard Blewett [DevelopMentor]

When you allocate an array the runtime zeros the memory - fullstop.

So for reference types you get an array of null references and for value types (structs) you get an array of zeroed value types. This is the reason behind why you cannot declare a custom *default* constructor on a value type - if you did the runtime would have to execute it as many times as there are members of the array - which could be a significant hidden overhead in array allocation.

Also, when you write the code

MyStruct[] s = new MyStruct[100];
s[23] = new MyStruct(40, 2);

the second line is not creating anything, its simply re-initializing an already allocated block of memory. So while, in theory, running the contructor as part of array allocation using the (made up) syntax

MyStruct[] s = new MyStruct[100](40, 2); // REPEAT: I HAVE JUST INVENTED THIS SYNTAX

causes the constructor to run 100 times - so does the following.

MyStruct[] s = new MyStruct[100];
for( int i = 0; i < s.Length; i++ )
{
s = new MyStruct(40, 2);
}

And internally the runtime would have to loop over each piece of memory to run the constructor as well, so there is no real difference between the two - except that the cost is very obvious in the latter example whereas it is less obvious in the first.

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

Well, as a matter of fact I_HAD_MISSED a basic thing or two, anyway,
although Ollie's answer makes perfectly sense when dealing with
classes, it doesn't seem to me to apply as well if you have to
instantiate an array of structures; consider the following useless
code :
 

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