Should I explicitly initialize all member variables?

  • Thread starter Thread starter Guest
  • Start date Start date
Mike Schilling said:
I don't see any exaxmples there of fields explicitly being set to their
default values, e.g.

int i = 0;

or

String s = null;

*That's* what I'm thinking the JIT could eliminate the code for.

Right, Not explicitly but implicitly for the first assignment where Bar.s is
null.
But as I replied to Jon, this is something that should be done by the
language compilers not by the JIT because different languages emit different
initializer constructs in IL, and you can't let them pay for what they don't
need at the JIT level.

Willy.
 
Jon... Apparently I can call int i; i.ToString() _without_ boxing. This
implies that int i is a struct that does derive from value which derives
from object. I am a bit confused here.

http://www.csharpcorner.com/Code/2003/July/BoxNUnboxSSF.asp

Regards,
Jeff

Value types *don't* actually derive from anything - only the reference
type which is used for boxing the value type derives (indirectly) from
Object. It's all a bit odd, but is spelled out in the CLI spec.
 
Jeff Louie said:
Jon... Apparently I can call int i; i.ToString() _without_ boxing. This
implies that int i is a struct that does derive from value which derives
from object.

No, it doesn't. It just means that ToString() is overridden in Int32,
so the compiler already knows which version to call - there's no need
to box.

If ToString weren't overridden, it would require a box. Try it with
your own value type and see.

That page doesn't load for me, I'm afraid.
 
Hmm. Do you have an online reference to this part of the CLI spec. I am
begining to think this is a fine semantic argument about the meaning of
"derives from." If int32 honors the contract/interface of object, then
one could argue that it indeed does "derive" from object.

Regards,
Jeff

No, it doesn't. It just means that ToString() is overridden in Int32,
so the compiler already knows which version to call - there's no need
to box.
 
Jeff Louie said:
Hmm. Do you have an online reference to this part of the CLI spec. I am
begining to think this is a fine semantic argument about the meaning of
"derives from." If int32 honors the contract/interface of object, then
one could argue that it indeed does "derive" from object.

Well, one could argue it, but then one would be ignoring the
definitions of derivation etc :)

In the C# spec, section 14.4.3 (ECMA numbering) it specifies:

<quote>
# If M is an instance function member declared in a value-type:

* E is evaluated. If this evaluation causes an exception, then no
further steps are executed.
* If E is not classified as a variable, then a temporary local
variable of E's type is created and the value of E is assigned to that
variable. E is then reclassified as a reference to that temporary local
variable. The temporary variable is accessible as this within M, but
not in any other way. Thus, only when E is a true variable is it
possible for the caller to observe the changes that M makes to this.
* The argument list is evaluated as described in §14.4.1.
* M is invoked. The variable referenced by E becomes the variable
referenced by this.

# If M is an instance function member declared in a reference-type:

* E is evaluated. If this evaluation causes an exception, then no
further steps are executed.
* The argument list is evaluated as described in §14.4.1.
* If the type of E is a value-type, a boxing conversion (§11.3.1)
is performed to convert E to type object, and E is considered to be of
type object in the following steps. [Note: In this case, M could only
be a member of System.Object. end note]
</quote>

which I think is pretty much what I said - basically, you only need to
box if the method being called isn't actually declared in the value
type.
 
The best practice is in any case to initialize member variables in the
constructor.

There are some specific behaviors according to the type of the app. In
ASP.Net, for instance, if you initialize the variable within a class and
not within a constructor (page_init) then each time the page loads the
variable will get initialized to that value rather than the current
value. This is also due to the statelessness of the Http protocol.

with regards,


J.V.Ravichandran
- http://www.geocities.com/
jvravichandran
- http://www.411asp.net/func/search?
qry=Ravichandran+J.V.&cob=aspnetpro
- http://www.southasianoutlook.com
- http://www.MSDNAA.Net
- http://www.csharphelp.com
- http://www.poetry.com/Publications/
display.asp?ID=P3966388&BN=999&PN=2
- Or, just search on "J.V.Ravichandran"
at http://www.Google.com
 
Ravichandran J.V. said:
The best practice is in any case to initialize member variables in the
constructor.

I disagree - I tend to prefer to do it at the variable declaration if
it's going to be the same value whichever constructor is invoked.
There are some specific behaviors according to the type of the app. In
ASP.Net, for instance, if you initialize the variable within a class and
not within a constructor (page_init) then each time the page loads the
variable will get initialized to that value rather than the current
value. This is also due to the statelessness of the Http protocol.

But page_init is not the constructor for the class, as I *think* you
were implying it was. (If you weren't, please explain the middle
sentence above - it doesn't make much sense at the moment.)

Except in a few *very* unusual circumstances, leaving the values as the
default ones, explicitly setting those values in the constructor, and
explicitly setting those values in the variable declarations will all
have the same effect.
 
Jon... If this means M(E) I wonder if this is just saying that if M is
declared in a
reference type and is passed E that is a value type, then E will be
boxed. So
System.Console.WriteLine(valueType) valueType is boxed whereas
valueType.ToString() there is no boxing. Either way all valueTypes honor
the
ToString() method which appears to represent polymorphic behavior.

Regards,
Jeff
 
Jeff Louie said:
Jon... If this means M(E) I wonder if this is just saying that if M is
declared in a reference type and is passed E that is a value type,
then E will be boxed.

No, it's not M(E). If you look at the bit of the spec I was referring
to, E is the instance expression - i.e. what the method is going to be
invoked *on*.
So System.Console.WriteLine(valueType) valueType is boxed whereas
valueType.ToString() there is no boxing. Either way all valueTypes honor
the ToString() method which appears to represent polymorphic behavior.

No, the value types themselves don't honour ToString - their boxed
equivalents do, because the boxed types derive (indirectly) from
Object.

The difference here is that C# contrives to make it look like value
types derive from Object indirectly, but the CLR doesn't - and IMO it's
important to know the difference. Indeed, the C# spec actually refers
to value types deriving from Object implicitly, which I think is part
of the problem - it's a bad way of specifying the language, as it hides
the nature of value types as far as the CLR is concerned. I wouldn't be
surprised if analysing the C# spec closely would throw up some
inconsistencies due to this.

Take, for example, section 8.2.4 (which is part of section 8 which is
only a note, admittedly) - it states: "An int value can be converted to
object and back again to int". If int actually derives from object,
there shouldn't be any conversion necessary, just as it would make no
sense to talk about converting a string to an object.

Put it this way - while the CLR explanation (with its boxed type of the
same name business) is slightly more complicated at first sight, it's a
lot simpler in the long run. You don't need to treat inheritance with
value types as different from inheritance with reference types, because
you just state that there *is* no inheritance with value types.

It's a little bit like my old bugbear of people saying that objects are
passed by reference - it's supposedly a simplification, but the hoops
you have to jump through just to avoid stating the truth aren't worth
it IMO.
 
Hi Jon... This looks more like "ad-hoc" polymorphism as opposed to
"subclass"
polymorphism where the compiler may need to convert/coerce the valueType
to
a reference type and call ToString() on the reference.

Regards,
Jeff
 
Jeff Louie said:
Hi Jon... This looks more like "ad-hoc" polymorphism as opposed to
"subclass"
polymorphism where the compiler may need to convert/coerce the valueType
to
a reference type and call ToString() on the reference.

Exactly. But when ToString() is actually declared in the value type as
well, rather than getting the Object (or System.ValueType)
implementation, no boxing is required.
 
Jon Skeet said:
Exactly. But when ToString() is actually declared in the value type as
well, rather than getting the Object (or System.ValueType)
implementation, no boxing is required.

Is

public String ToString() { return base.ToString();}

an optimization, or does the base call require boxing?
 
Mike Schilling said:
Is

public String ToString() { return base.ToString();}

an optimization, or does the base call require boxing?

Good question. Not sure, but I suspect it involves a box. The easiest
thing would be to try it an look at the IL :)
 
Jon Skeet said:
Good question. Not sure, but I suspect it involves a box. The easiest
thing would be to try it an look at the IL :)

You asked for it: :-)

public struct HasOverride {
public int i;

public override String ToString() {
return base.ToString();
}
}

results in:

..method public hidebysig virtual instance string
ToString() cil managed
{
// Code size 21 (0x15)
.maxstack 1
.locals init ([0] string CS$00000003$00000000)
IL_0000: ldarg.0
IL_0001: ldobj HasOverride
IL_0006: box HasOverride
IL_000b: call instance string
[mscorlib]System.ValueType::ToString()
IL_0010: stloc.0
IL_0011: br.s IL_0013
IL_0013: ldloc.0
IL_0014: ret
} // end of method HasOverride::ToString

So your suspicion is correct.
 
Back
Top