remove struct's default constructor?

Z

Zytan

I have a struct constructor to initialize all of my private (or public
readonly) fields. There still exists the default constructor that sets
them all to zero. Is there a way to remove the creation of this
implicit default constructor, to force the creation of a struct via my
constructor only?

Zytan
 
R

rossum

I have a struct constructor to initialize all of my private (or public
readonly) fields. There still exists the default constructor that sets
them all to zero. Is there a way to remove the creation of this
implicit default constructor, to force the creation of a struct via my
constructor only?

Zytan
Declare your own default constructor private:

struct MyStruct {

public MyStruct(int data) {
// Do stuff
}

private MyStruct() { }
}

Because you have declared your own default constructor the compiler
will not create one. Because you have declared it private no-one
except you can ever call it. This makes your struct impossible to
default construct, which will limit its use in some situations.

rossum
 
D

David Browne

rossum said:
Declare your own default constructor private:

struct MyStruct {

public MyStruct(int data) {
// Do stuff
}

private MyStruct() { }
}

error CS0568: Structs cannot contain explicit parameterless constructors

David
 
W

Willy Denoyette [MVP]

Zytan said:
I have a struct constructor to initialize all of my private (or public
readonly) fields. There still exists the default constructor that sets
them all to zero. Is there a way to remove the creation of this
implicit default constructor, to force the creation of a struct via my
constructor only?

Zytan


Not sure what you mean here with default constructor, there is no such thing as a "default"
constructor for structs.
If you don't supply a constructor, the struct will get initialized by the runtime, such that
all its fields have their default value, that is, the memory space (f.i on the stack) taken
by the struct is set to 0. There is no way to suppress this "initialization ", which is a
good thing.

Willy.
 
Z

Zytan

Not sure what you mean here with default constructor, there is no such thing as a "default"
constructor for structs.

http://msdn2.microsoft.com/en-us/library/x2xcf8ft(vs.80).aspx

"Each struct already has a default constructor that initializes the
object to zero. Therefore, the constructors that you can create for a
struct must take one or more parameters."
If you don't supply a constructor, the struct will get initialized by the runtime, such that
all its fields have their default value, that is, the memory space (f.i on the stack) taken
by the struct is set to 0.

Yes, by the default constructor.
There is no way to suppress this "initialization ", which is a
good thing.

No, it's bad. Because I have a struct that contains only private data
members, as Jon Skeet wondefully pointed out is a good thing to do.
Therefore, I can only initialize those private members via constructor
(or declaration assignment -- I am not sure of the terminology of
that). Thus, if the default constructor does not disappear once I
create my own struct constructor, the caller can create a struct still
using the default constructor, setting all private / readonly fields
to 0, and they can never be changed. This is unfortunate for any
struct that has manually created constructors / properties that so
validity checking on the parameters.

(Althouhgh, for structs that have NO manually created constructors, I
agree that the default constructor that sets all fields to 0 is a good
thing.)

Zytan
 
Z

Zytan

Declare your own default constructor private:
private MyStruct() { }

http://msdn2.microsoft.com/en-us/library/x2xcf8ft(vs.80).aspx
"Compiler Error CS0568
Error Message
Structs cannot contain explicit parameterless constructors
Each struct already has a default constructor that initializes the
object to zero. Therefore, the constructors that you can create for a
struct must take one or more parameters."
Because you have declared your own default constructor the compiler
will not create one. Because you have declared it private no-one
except you can ever call it. This makes your struct impossible to
default construct, which will limit its use in some situations.

Yes, that thought works in C++ to prevent instantiation (to create
'static' classes that C++ does not support), and I thought maybe I
could do it in C#, as you've thought, as well, but it doesn't work.

Zytan
 
W

Willy Denoyette [MVP]

Zytan said:

Ever heard of mistakes in MSDN?
"Each struct already has a default constructor that initializes the
object to zero. Therefore, the constructors that you can create for a
struct must take one or more parameters."


Yes, by the default constructor.
No there is no *explicit* .ctor created by the compiler for a value type as it's the case
for a class, take a look at the IL using ildasm.
 
W

Willy Denoyette [MVP]

Zytan said:
http://msdn2.microsoft.com/en-us/library/x2xcf8ft(vs.80).aspx

"Each struct already has a default constructor that initializes the
object to zero. Therefore, the constructors that you can create for a
struct must take one or more parameters."


Yes, by the default constructor.


No, it's bad. Because I have a struct that contains only private data
members, as Jon Skeet wondefully pointed out is a good thing to do.
Therefore, I can only initialize those private members via constructor
(or declaration assignment -- I am not sure of the terminology of
that). Thus, if the default constructor does not disappear once I
create my own struct constructor, the caller can create a struct still
using the default constructor, setting all private / readonly fields
to 0, and they can never be changed. This is unfortunate for any
struct that has manually created constructors / properties that so
validity checking on the parameters.

What else do you want? structs are stored on the stack (or inlined with a heap allocated
object instance), that means if the fields are not set to their default value, that they
will contain the trash that's still in the stack.

say you have:
struct S
{
int i;
SomeObject obj;
}

if S wouldn't be set to 0, SomeObject could contain an address, left on the stack from a
previous call frame possibly containing a valid pointer or even a valid object reference,
but not a reference of SomeObject type, use your imaginatio and think what could happen in
such case....

(Althouhgh, for structs that have NO manually created constructors, I
agree that the default constructor that sets all fields to 0 is a good
thing.)

No, its a perfect thin for all. If you don't want the struct to be initialized with default
values, make sure they are initialized correctly and handle the error cases.


Willy.
 
Z

Zytan

Not sure what you mean here with default constructor, there is no such thing as a
Ever heard of mistakes in MSDN?

Yes. Why the attitude? It's ok to be called on something you believe
is right.

I believe MSDN is correct this time because of further evidence
explained below.
No there is no *explicit* .ctor created by the compiler for a value type as it's the case
for a class, take a look at the IL using ildasm.

Perhaps just because it is not explicitly created, it doesn't mean
that it's conceptually not there. Any basic value data type would be
foolish to have a constructor when all you need to do is shove zero(s)
into memory address(es).

So, you are saying there is no default constructor for structs, not
even conceptually? Then why does C# refuse the attempt to create a
struct constructor with no parameters? If there's no default
constructor, there should be no issue doing so. I think the reason
why is that one is implied, even thought it doesn't actually exist
explicitly in the byte code.

I think it is perhaps pedantic to state there is no constructor if
there really is one conceptually, but just not explicitly in the byte
code. But, I could be wrong. I don't know enough to know for sure.
I don't know what conceptual designs the byte code hides, if any.

Zytan
 
Z

Zytan

No, it's bad. Because I have a struct that contains only private data
What else do you want? structs are stored on the stack (or inlined with a heap allocated
object instance), that means if the fields are not set to their default value, that they
will contain the trash that's still in the stack.

Willy, you are missing my point.

Yes, junk would exist if no constructor is called. But, if I force
any use of a struct to use my constructor, then the values will be
what the constructor forces them to be. This is even better than
having them zeroed out. Imagine only having proper values. Zerod
values are better than junk values. Proper values are even better
than zeroed values.
if S wouldn't be set to 0, SomeObject could contain an address, left on the stack from a
previous call frame possibly containing a valid pointer or even a valid object reference,
but not a reference of SomeObject type, use your imaginatio and think what could happen in
such case....

I know all about it, Willy. I think it's great that languages
determine when variables are used before they are initialized, and C++
(at run time) and C# (at compile time, even better) are two such
languages. The above scenario, should never occur, even if variables
are not zeroed out. But, yes, zeroing them out adds an extra layer of
protection, I agree.
No, its a perfect thing for all.

No, it's not perfect for all. How can you claim that? For my struct,
it should never, ever have zeros in it. Ever. Zeros are just not
proper values. Either the struct doesn't exist, or it exists with
specific values passed into its constructor. There is never a time
that it ever makes sense to have zeroes in it. Thus, if I can force
my constructor to be invoked every single time the struct is used,
then in all cases in the program, the struct will only ever contain
real, proper values, and will never contain imporper zero values.

To make such a claim "something is perfect for all" implies you've
thought of infinite possible cases. It's an impossible claim to make,
and can be disproven with a single case. I thought I had explained
that case prior to this post. I hope the above explains it
adequately.

I am dumbfounded as to your defensive behaviour. Did it arrive from
my claim that you were wrong that structs don't have a constructor?
All I am trying to do is find the truth by discussion. If I'm wrong,
I don't care, as long as I find the truth. My being wrong on one
thing doesn't make me automatically wrong on another.
If you don't want the struct to be initialized with default
values, make sure they are initialized correctly and handle the error cases.

But that means I must manually do what the compiler could handle for
me. I think the arrival of strict type checking showed why it is best
that the compiler handle as much as it can, since humans are prone to
error.

Zytan
 
C

Carl Daniel [VC++ MVP]

Yes, junk would exist if no constructor is called. But, if I force
any use of a struct to use my constructor, then the values will be
what the constructor forces them to be. This is even better than
having them zeroed out. Imagine only having proper values. Zerod
values are better than junk values. Proper values are even better
than zeroed values.

It comes down to this: There's a deeply rooted assumption in the CLR that:

1. value types can always be copied as memory images.
2. that storage for a value type can always be initialized by filling the
memory with zeros.

If you can't live with those constraints, use a reference class instead of a
struct.

-cd
 
B

Bruce Wood

It comes down to this: There's a deeply rooted assumption in the CLR that:

1. value types can always be copied as memory images.
2. that storage for a value type can always be initialized by filling the
memory with zeros.

Ah. Finally. I was going to point that out.

Willy is right: in effect there _is no default constructor_. It was
omitted for value types for efficiency reasons. When you say:

public class Foo
{
private int x;
private float y;
private MyStruct z;
}

what happens is that all of the private field space for Foo is filled
with zeroes. The three fields aren't constructed individually. Then
Foo's constructor is run. If Foo's constructor forgets to initialize z
is some meaningful way, then it is left as it was: filled with zeroes.
All references it may contain are null, all integers are zero, all
booleans are false.

There is no default constructor, neither implied nor explicit. That is
to say, there is no piece of code emitted with the express job of
initializing MyStruct z, just some code that runs to generally
initialize the memory where Foo's state will go. This was, I believe
to make it cheap to create value types: there is never a need to call
implicit constructors: just a need to call explicit constructors if
you should invoke them in your code.

So what do you do in your MyStruct to handle this? One of two things:

1) Have MyStruct explicitly check for an un-constructed state and flag
it as illegal, usually by throwing an exception on property access /
method calls that can't be done before the struct is constructed
explicitly. I tend to avoid this because it just causes a mess at run-
time.

2) Give all-zeroes an interpretation. Decide what it means, and handle
that situtation. For example, in my Measure struct, all zeroes (and
nulls) means a scalar zero measurement (zero with no unit of measure
attached).

Structs are supposed to be very small and very simple. If your struct
starts to grow to be large and/or complicated then IMHO it's time to
re-evaluate the design.
 
W

Willy Denoyette [MVP]

Zytan said:
Willy, you are missing my point.

Yes, junk would exist if no constructor is called. But, if I force
any use of a struct to use my constructor, then the values will be
what the constructor forces them to be. This is even better than
having them zeroed out. Imagine only having proper values. Zerod
values are better than junk values. Proper values are even better
than zeroed values.


I know all about it, Willy. I think it's great that languages
determine when variables are used before they are initialized, and C++
(at run time) and C# (at compile time, even better) are two such
languages. The above scenario, should never occur, even if variables
are not zeroed out. But, yes, zeroing them out adds an extra layer of
protection, I agree.


No, it's not perfect for all. How can you claim that? For my struct,
it should never, ever have zeros in it. Ever. Zeros are just not
proper values. Either the struct doesn't exist, or it exists with
specific values passed into its constructor. There is never a time
that it ever makes sense to have zeroes in it. Thus, if I can force
my constructor to be invoked every single time the struct is used,
then in all cases in the program, the struct will only ever contain
real, proper values, and will never contain imporper zero values.

To make such a claim "something is perfect for all" implies you've
thought of infinite possible cases. It's an impossible claim to make,
and can be disproven with a single case. I thought I had explained
that case prior to this post. I hope the above explains it
adequately.

I am dumbfounded as to your defensive behaviour. Did it arrive from
my claim that you were wrong that structs don't have a constructor?
All I am trying to do is find the truth by discussion. If I'm wrong,
I don't care, as long as I find the truth. My being wrong on one
thing doesn't make me automatically wrong on another.


But that means I must manually do what the compiler could handle for
me. I think the arrival of strict type checking showed why it is best
that the compiler handle as much as it can, since humans are prone to
error.

Zytan
 
W

Willy Denoyette [MVP]

Zytan said:
Yes. Why the attitude? It's ok to be called on something you believe
is right.
This is not about attitude this is about reality, many things in MSDN are "wrong or "badly
worded", you can't and should never expect such huge piece of documentatin to be perfect.
It's up to the reader to correctly interpret what's been written, or to ask MSFT to correct
what's wrong.
I believe MSDN is correct this time because of further evidence
explained below.


Perhaps just because it is not explicitly created, it doesn't mean
that it's conceptually not there. Any basic value data type would be
foolish to have a constructor when all you need to do is shove zero(s)
into memory address(es).
No, it's not there, the fact that the memory is initialized with zero values, doesn't make
it a constructor.
The CLR goes to great lengths to assure that all memory allocated for the "object" on the GC
heap, or, a "value" on the Stack, is initialized with zero's before any explicit or compiler
generated constructor runs for the type.
Reference types (depending on their location on the GC heap) are stored on:
1) zero'd out memory pages, or
2) explicit zero'd out memory locations , no surprises here, this is all taken care of
by the CLR's memory allocator.
The stack locations that hold a value type will get:
1) properly aligned, depending on the platform requirements, and,
2) properly initialized at 0, *before* usage, that is, before a (possible) user defined
constructor runs.
Here, this initialization is taken care of by the JIT, who produces the fasted code possible
on the platform (xmm/sse).
Alll this is done before an *possible* constructor runs, it's even not part of the actual
"constrution".

Willy.
 
R

rossum

http://msdn2.microsoft.com/en-us/library/x2xcf8ft(vs.80).aspx
"Compiler Error CS0568
Error Message
Structs cannot contain explicit parameterless constructors
Each struct already has a default constructor that initializes the
object to zero. Therefore, the constructors that you can create for a
struct must take one or more parameters."


Yes, that thought works in C++ to prevent instantiation (to create
'static' classes that C++ does not support), and I thought maybe I
could do it in C#, as you've thought, as well, but it doesn't work.

Zytan
Sorry about my mistake, I did indeed have my C++ hat on.

You could use a class as others have suggested. If you still want to
use a struct then add a bool field validConstructor. This will
default initialise to false, and can be set to true in your explicit
constructors. Check it at the start of those methods which cannot
handle zero values for all fields.

rossum
 
Z

Zytan

Sorry about my mistake, I did indeed have my C++ hat on.

Hey, no problem. I thought the same thing.
You could use a class as others have suggested. If you still want to
use a struct then add a bool field validConstructor. This will
default initialise to false, and can be set to true in your explicit
constructors. Check it at the start of those methods which cannot
handle zero values for all fields.

Yes, these are valid solutions. Thanks. I don't think my issue is
large enough to warrant any of these things. I am more just curious
as to why I can't remove the default zeroing out.

Zytan
 
Z

Zytan

Ever heard of mistakes in MSDN?
This is not about attitude this is about reality, many things in MSDN are "wrong or "badly
worded", you can't and should never expect such huge piece of documentatin to be perfect.
It's up to the reader to correctly interpret what's been written, or to ask MSFT to correct
what's wrong.

Answering a question with a snappy question is attitude. I don't
expect MSDN to be completely correct. MSDN is giving strong evidence
that it is true, so I believe it just may be true. When C# refuses to
allow me to make a constructor with 0 parameters, and MSDN tells me
explicitly that the reason I cannot do this is because a default
constructor already exists, then, yes, I am going to believe it. The
evidence supports this.
No, it's not there, the fact that the memory is initialized with zero values, doesn't make
it a constructor.
The CLR goes to great lengths to assure that all memory allocated for the "object" on the GC
heap, or, a "value" on the Stack, is initialized with zero's before any explicit or compiler
generated constructor runs for the type.
Reference types (depending on their location on the GC heap) are stored on:
1) zero'd out memory pages, or
2) explicit zero'd out memory locations , no surprises here, this is all taken care of
by the CLR's memory allocator.
The stack locations that hold a value type will get:
1) properly aligned, depending on the platform requirements, and,
2) properly initialized at 0, *before* usage, that is, before a (possible) user defined
constructor runs.
Here, this initialization is taken care of by the JIT, who produces the fasted code possible
on the platform (xmm/sse).
Alll this is done before an *possible* constructor runs, it's even not part of the actual
"constrution".

Ok, thanks for the in depth explanation. Things are always zeroed out
before a constructor is called. I get it. In fact, I think it's
great.

But, this doesn't prove that there is no default constructor for
structs. If the default cosntructor for structs is just to zero
things out, then it doesn't need to exist, and therefore doesn't have
to exist in the final byte code. The fact that everything is zeroed
out is one of the reasons such a default constructor needn't actually
exist, since it'd just do the same work again.

Again, I will ask: Why does C# disallow a parameterless constructor?
MSDN says it is because a default parameterless constructor exists.
If MSDN is wrong, then shouldn't the creation of a parameterless
constructor be allowed?

Zytan
 
Z

Zytan

It comes down to this: There's a deeply rooted assumption in the CLR that:
1. value types can always be copied as memory images.
2. that storage for a value type can always be initialized by filling the
memory with zeros.

If you can't live with those constraints, use a reference class instead of a
struct.

Ok, I understand. And I've always been happy that things are zeroed
out. Yet, it would be better if I could force my own constructor, but
structs are value types, and that breaks the CLR assumption. I get
it. It was just a question, and I know the answer now. I'll use a
class if that forced construction is that important to me.

Thanks,

Zytan
 
Z

Zytan

Willy is right: in effect there _is no default constructor_. It was
omitted for value types for efficiency reasons.

Ok, I know that no constructor is actually called, and yes, I totally
agree it is worth while for efficiency reasons. Imagine calling a
constructor for every int!
There is no default constructor, neither implied nor explicit. That is
to say, there is no piece of code emitted with the express job of
initializing MyStruct z, just some code that runs to generally
initialize the memory where Foo's state will go. This was, I believe
to make it cheap to create value types: there is never a need to call
implicit constructors: just a need to call explicit constructors if
you should invoke them in your code.

Yes, and again, I agree. It makes it quick.

But, you are just saying no code is run to initialize the value types
(which makes sense since it'd be slow). This doesn't prove that
conceptually there is no default cosntructor. Why doesn't C# allow me
to make a parameterless constructor if there is no default
constructor? I can see no reason why C# would disallow a
parameterless constructor *unless* one already exists, which is what
MSDN says, which is why I believe it (although, I know it is wrong a
lot of the time).

So far, the only evidence either way supports that (at least
conceptually) a default parameterless constructor exists for struct.
So what do you do in your MyStruct to handle this? One of two things:

1) Have MyStruct explicitly check for an un-constructed state and flag
it as illegal, usually by throwing an exception on property access /
method calls that can't be done before the struct is constructed
explicitly. I tend to avoid this because it just causes a mess at run-
time.

I've done this for C++ to allow static classes which it doesn't
support. I dislike it, but there was no better choice.
2) Give all-zeroes an interpretation. Decide what it means, and handle
that situtation. For example, in my Measure struct, all zeroes (and
nulls) means a scalar zero measurement (zero with no unit of measure
attached).

Yes. It is quite convenient that every data type means something
decent when its bytes are zeroed out, isn't it?
Structs are supposed to be very small and very simple. If your struct
starts to grow to be large and/or complicated then IMHO it's time to
re-evaluate the design.

My struct is quite simple. A zeroed out struct means nothing,
unfortunately, but it's not complicated enough to require a class. If
this becomes an issue, I'll use a class.

Thanks for the explanation, and plausible options!

Zytan
 

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