Reputation: 435
I am wondering how to get the default value of a field of any arbitrary class.
For example,
public class Example
{
public int a = 10;
}
I want to get the value 10
when only typeof(Example)
is given.
This default value is useful because I am writing a function to create a non-null default instance for any type. It would be nice to have the instance initialized to the values given in the declaration.
Please note that creating an instance through a default constructor and grab the value is not an option to me because I hope the function I am working on can be applied to classes with or without default constructors.
Also, DefaultValueAttribute
is not an option for me either. As far as I know, attributes can only take several types as its argument. So I cannot get the default value of fields of self-defined types.
Edit 1:
I know this question seems to be a duplication of Get default value of class member, but it is not. In the referenced question, the OP is satisfied with using constructor to get a real instance of the class. But in my case, I cannot be sure that a default constructor exists for the class I am dealing with.
I am writing a default value generator because I need a fake object of an arbitrary type. That is, there is no assumption made of how the type is going to be. The fake object will be inspected through a GUI, and a user can edit the values of fields that are exposed in the inspector. Here the arbitrary type is important to me because the inspector should work on not only types defined by me but also on types defined in libraries. Moreover, the fake object should never be null or the inspector will blow up, LOL.
FormatterServices.GetSafeUninitializedObject
gets me an acceptable fake object as it allocates memory blocks and initialize them to zeros. But I feel like it would be better if the fake object can be further initialized so the fields can have their default values shown in the inspector.
Thanks to Patrick Hofman reminds me that the "default value" I am talking about is not the real default but a expression that will be evaluated in constructors. That being said, I am still wondering if it is possible to fetch the field initialization expression and event evaluate it.
I think there should be a way of doing it because decompilers such as ILSpy can shows the field initializer in the decompiled results.
Upvotes: 3
Views: 1568
Reputation: 61952
You can inspect the IL code, and look for members called .ctor
(these are the instance constructors).
Then find one which does not call
another Example::.ctor
overload, but calls instead a base-class constructor, in your case [mscorlib]System.Object::.ctor()
. (If there does not exist one, the instance field initializers are unreachable (pathological case)!)
Then, inside the IL of this member, the field assignments stfld
that come before the call to the base class .ctor
, are the field initializers. Voilà!
Upvotes: 2
Reputation: 156978
You can only get values of constants, not any other type of variables, since they need to have an initialized class to retrieve a value from, which aren't real defaults any more, just the current value.
The previously duplicate Get default value of class member tells what to do if you drop the don't create an instance constraint.
What about this one?
public class Example
{
public readonly DateTime a = DateTime.Now;
}
Can you tell me what the default value of this field is? Even if you could, it isn't really the default value, it is the evaluated value of a certain variable in a point-in-time.
Upvotes: 4