So, basically, it is regarded as a default constructor. It's just
No. Its' not that structs can't have parameterless constructors, it's the C# compiler that
doesn't emit such constructor (called a "default constructor"), and doesn't allow you to
define a parameterless constructor in C#.
The zero initialization you are noticing and what you call a "default constructor", comes
from;
1) the 'initlocals 'flag set in the method metadata by the C# compiler, this flag is a hint
for the JIT to initialize all local variables to zero, so, a local variable holding a struct
is zero initialized because of a default action on all the locals.
2) for embedded structs, it comes from the fact that the memory allocated for a reference
instance on the GC heap is zeroed by the GC/memory allocator, but not by a constructor.
Ok, yes, I know something else zeroes the memory. What I am saying is
that because of these other things that zeor the memory, there is no
need to call a constuctor that does so, thus, the byte code or IL code
or whatever it is that is created from the C# code, doesn't explicitly
call a constructor. It would be foolish for two reasons: 1. to repeat
the zeroing out, and 2. it's just plain slow.
Now, because the code that is created / compiled from the C# code,
whether its byte code or IL code, whatever it is called, I have no
idea, but my point is, just because whatever created this code is
smart enough to realize, hey, yeah, don't call a constructor for all
basic value types and all structs since they are already zeroed out by
the methods you've described, it doesn't *mean* that the C# language
doesn't have a constructor.
What I am trying to say is: Everything I am saying could be
absolutely true, and the result is precisely what you see: no
constructor calls in the IL.
Now, if you continue to call this a "default constructor" or a "conceptual constructor", no
problem for me. But I know they are not constructors "pure sang".
It is very convenient to call it a default constructor, because
everything flows into place with that thought.
And, yes, I can see that it does from your perspective, too.
So, it's basically up to the language designers to say what it what.
Given the evidence, I highly suspect that default constructors for
struct is a concept that they created.
I'm not talking about byte code ether, I'm talking about what is produced by the #C
compiler, that is, no "default constructor".
What? Isn't "what is produced by the #C compiler" == "byte code"? If
not, replace "byte code" with "IL". Or replace it with whatever
should be there. Whatever that is called, that's what I'm talking
about, and excuse my lack of knowledge with the terminology. I will
use "IL" from now, assuming that's correct.
Yes, IL has no constructor call. I know. You've proven that.
This does not mean C# doesn't have a constructor there. Just because
the compiler is smart enough to not make it have one, then it's ok.
It's like constructors for basic data types in C++, you can call them,
but you know that down in the assembly code that is made, there is no
function call to any constructor. It just stores the value right into
memory. It doesn't mean the constructor doesn't exist, and in fact,
you can initialize a variable with constructor like syntax, which
shows at the C++ level, it does exist. IL is not C#. I guess that's
the issue. It's like you're looking under the hood, and seeing
'what's really there', and you're saying 'hey, no constructor call!
thus, C# structs have no constructor'.
This is not about optimizing out.
If C# structs have default constructors, then, yes, they are.
I have to disagree, with what MSDN says, the page you are refering to is "too strong worded,
and confusing.
<snip
Structs cannot contain explicit parameterless constructors
I would agree when there was written, "C# Structs cannot contain...". Structs is too broad a
term here, see later for a sample that proves that structs (aka value types) can have
"explicit parameterless constructors" .
Do you mean that basic value types are structs? I think that's a case
where C# says they are structs, but you know deep down inside, they
are not anything but a memory address. That's how digging down can
lead you to the wrong conclusion about the high level language.
To illustrate my point consider following sample written in ILasm (just another (low level)
language on the platform) which allows you to declare a parameterless constructor.
//compile: ilasm /out:mystruct.dll /dll mystruct.il
.assembly extern mscorlib {}
.assembly mystruct{}
.class public sequential ansi sealed beforefieldinit S
extends [mscorlib]System.ValueType
{
.field public int32 ii
.field public int64 l
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
ldc.i4.2 // store 2 in field l
conv.i8
stfld int64 S::l
ret
}
}
Do yourself a favor, and compile it and look at the IL using ildasm, you'll notice the
parameterless constructor .ctor (which is not emitted by C# for structs).
Yes, I know, I trust you, I don't need to compile this. I know that IL
makes a parameterless constructor which C# does not 'emit' into IL
code. I know this.
What I am saying is that doesn't matter. It matters no more than the
function call that was optimized out of existance, so it doesn't
appear in IL. You'd never say that function didn't exist. The IL
doesn't have to match C#. As long as it does what actual, non-
optimized, stupidly created IL could would do based precisely on the
C# syntax, it's ok. Speed is an issue, so basic types do not call
constructors, just as they don't in C++. It doesn't mean they are not
conceptually there at the *high level language*.
Now let's try to use this value type from C# (or from VB or C++/CLI whatever):
// comile: csc /r:mystruct.dll thisfile.cs
class Program
{
static void Main()
{
S ms = new S();
Console.WriteLine("{0} - {1}", ms.ii, ms.l);
}
}
this will output 0 - 2, you see that C# supports calling parameterless constructors, only
that it doesn't allow to produce one, and that's what I'm trying to say since days now.
I don't think this is a fair call. You're creating non-C# code. Yes,
I agree that C# doesn't let you make parameterless constructor.
Conceptually, this is because the optimizied IL code doesn't call one,
and couldn't possibly call your own in a decent enough way that the
designers could guarantee it be called, so the language denies your
right. I could make assembly code do anything, and call it from a
high level language, but that really says nothing about the high level
language. I could make C# call a function that does things beyond
what the language allows, but it doesn't mean C# 'knows' about this.
You're stepping out of bounds.
Again, your position is totally about the IL code generated. If you
think whatever IL code is generated IS what C# IS, then you're taking
a side that's impossible to argue against, because I'm talking about
C#, not the IL code. It is pointless to continue if this is the
position you hold, which I believe you've clearly shown. I don't
follow that logic, since the IL code can be vastly different. Ffor
instance, what do you say about C# static classes when looking at IL
code? Shouldn't you also hold C# to what the IL code is generated in
those cases, as well? It seems illogical to me, since you have to
pick and choose when you want to follow that stance or not. In terms
of default struct constructors existing, every piece fits. IL code is
out of bounds. If you pick that, why can't I go one step further and
start talking assembly, and say C# only supports JMP and CALL
instructions for program flow? I can't. It's out of bounds.
Zytan