6

Let's assume I have a class ClassWithMember

class ClassWithMember
{
    int myIntMember = 10;
}

How do I get the default value 10 of the myIntMember member by System.Type?

I'm currently struggling around with reflections by all I retreive is the default value of int (0) not the classes default member (10)..

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Ruben Aster
  • 153
  • 2
  • 8
  • 1
    10 is not the "default value". It's just the initial value of the field, which is compiled as an instruction that is part of the constructor – Thomas Levesque Jun 07 '10 at 14:15

4 Answers4

6

You can try something like this:

var field = typeof(ClassWithMember).GetField("myIntMember",
    BindingFlags.Instance | BindingFlags.NonPublic);
var value = (int)field.GetValue(new ClassWithMember());

The trick here is to instantiate an instance.

Anne Sharp
  • 119
  • 2
4

Try creating an instance an retreive the value with reflection.

Henrik Gering
  • 1,769
  • 16
  • 29
  • Unwillingly, since I also use classes (MonoBehaviour from Unity3D) that can't be instantiated that easy. – Ruben Aster Jun 07 '10 at 14:01
  • 3
    Just to elaborate: the default value of any int is 0, the assignment of your int to 10 is compiled as an assignment instruction in the constrictor, hence reflection is your choice, unless you want to refactor to "static readonly int DefaultValue = 10" and "myIntMember = DefaultValue" – Michael Stum Jun 07 '10 at 14:03
  • Reflection would be great but I don't get to the point where I get this specific value by type. – Ruben Aster Jun 07 '10 at 14:10
  • @Ruben If you can't instantiate the class, then it's a problem. You could in theory use Reflection to get the method body of the constructor and decompile the IL Code (Similar to how Reflector works), but that quite prone to breaking if the library changes. – Michael Stum Jun 07 '10 at 15:05
  • That's ok since it's only used inside the editor not the game-application itself. – Ruben Aster Jun 07 '10 at 15:10
2

If you're in control of the code for ClassWithMember, you could take a completely different approach to this by using the [DefaultValue] attribute from System.ComponentModel. Basically, what you'd do is write something like this:

class ClassWithMember
{
    public ClassWithMember()
    {
        SetDefaultValues();
    }

    [DefaultValue(5)]
    public MyIntMember { get; set; }
}

And then have a function like this somewhere, perhaps in a base class:

public void SetDefaultValues()
{
    foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(this))
    {
        DefaultValueAttribute a = prop.Attributes[typeof(DefaultValueAttribute)] as DefaultValueAttribute;
        if (a == null) 
            continue;
        prop.SetValue(this, a.Value);
    }
}

So now, you have a situation where you can easily retrieve the default values using Reflection.

Keep in mind that this is going to be quite a lot slower due to the Reflection requirement, so if this code gets instantiated a lot, you'll probably want to find a different approach. Also, it won't work with non-value types, due to a limitation with the .NET Framework's attribute support.

Warren Rumak
  • 3,824
  • 22
  • 30
0

You can still use Activator.CreateInstance to create a MonoBehaviour/ScriptableObject and check its values, if it's simply for the sake of checking the default Values. Make sure to use DestroyImmediate afterwards ;-)

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
Christoph Wolf
  • 95
  • 1
  • 12