Say you have a class declaration, e.g.:
class MyClass
{
int myInt=7;
int myOtherInt;
}
Now, is there a way in generic code, using reflection (or any other means, for that matter), that I can deduce that myInt has a default value assigned, whereas myOtherInt does not? Note the difference between being initialised with an explicit default value, and being left to it's implicit default value (myOtherInt will be initialised to 0, by default).
From my own research it looks like there is no way to do this - but I thought I'd ask here before giving up.
[Edit]
Even with nullable and reference types I want to distingush between those that have been left as null, and those that have been explicitly initialised to null. This is so that I can say that fields with an initialiser are "optional" and other fields are "mandatory". At the moment I'm having to do this using attributes - which niggles me with their redundancy of information in this case.
I compiled your code and load it up in ILDASM and got this
Note the
ldc.i4.7
andstfld int32 dummyCSharp.MyClass::myInt
seems to be instructions to set the default values for the myInt field.So such assignment is actually compiled as an additional assignment statement in a constructor.
To detect such assignment, then you will need reflection to reflect on the IL of MyClass's constructor method and look for
stfld
(set fields?) commands.EDIT: If I add some assignment into the constructor explicitly:
When I load it up in ILDASM, I got this:
Note that the extra assigment on myOtherInt that I added was affffded after a call the Object class's constructor.
So there you have it,
Any assignment done before the call to Object class's constructor in IL is a default value assignment.
Anything following it is a statement inside the class's actual constructor code.
More extensive test should be done though.
p.s. that was fun :-)
For value types using a nullable type for optional parameters should work. Strings could also be initialised to empty if they are not optional.
However this does strike me as a bit dirty, I would stick with attributes as a clear way of doing this.
What about making a generic struct that contains a value and an initialized flag?
Then just use this in place of the members you need to know about the initialization of. Its a pretty basic variation on a lazy future or promise.
The compiler can be set to generate a warning if you try to use a variable before assigning it a value. I have the default setting and that how it behave.
You might want to consider a nullable int for this behavior:
You could wrap the fields in private/protected properties. If you want to know if its been set or not, check the private field (e.g. _myInt.HasValue()).