44

I have a class:

class A {
    public string a = "A-val" , b = "B-val";
}

I want to print the object members by reflection

//Object here is necessary.
Object data = new A();
FieldInfo[] fields = data.GetType().GetFields();
String str = "";
foreach(FieldInfo f in fields){
    str += f.Name + " = " + f.GetValue(data) + "\r\n";
}

Here is the desired result:

a = A-val
b = B-val

Unfortunately this did not work. Please help, thanks.

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
SexyMF
  • 10,657
  • 33
  • 102
  • 206

3 Answers3

79

Once fixed to get rid of the errors (lacking a semi-colon and a bad variable name), the code you've posted does work - I've just tried it and it showed the names and values with no problems.

My guess is that in reality, you're trying to use fields which aren't public. This code:

FieldInfo[] fields = data.GetType().GetFields();

... will only get public fields. You would normally need to specify that you also want non-public fields:

FieldInfo[] fields = data.GetType().GetFields(BindingFlags.Public | 
                                              BindingFlags.NonPublic | 
                                              BindingFlags.Instance);

(I hope you don't really have public fields, after all...)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    The fields are public aren't they? – Martin Booth Oct 04 '11 at 14:22
  • 2
    @MartinBooth: Yeah, I was editing - basically it actually works okay with the code given, but I *suspect* that when it's not working, the OP has private fields. – Jon Skeet Oct 04 '11 at 14:34
  • 1
    I wasn't aware that you had to specify `BindingFlags.Instance` explicitly - I thought that would be the default. Without that flag, though, no fields were returned in my case. – Oliver Aug 20 '13 at 13:01
  • 1
    @Oliver: If you're specifying *any* flags, you need to specify it. The default it something like "public, instance, static". – Jon Skeet Aug 20 '13 at 13:16
  • 2
    @JonSkeet as of today 8/18/2015 the defaults I'm getting are: BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly; – honestduane Aug 19 '15 at 00:38
3

Remember when you write fields like :

public string VarName{ get; set;}

Then actually you have this code(this is what reflection see) :

private string _varName;
public string get_VarName(){
....
}
public void set_VarName(strig value){
....
}
  • 7
    Don't want to nitpick on an old post (thread-necro on 3 yr old post), but `public string VarName { get; set; }` is **not** a field at all. It's a property. To be specific, an autoproperty that, just as you write, creates a private field at compile-time. But the property itself is just a property. Just wanted to straighten that out if anyone happens to stumble across this and get confused. – Jerri Kangasniemi Nov 23 '16 at 21:27
1

As @Stanislav say, you must keep in mind the backing fields generated by the compiler for properties. If you want to exclude these fields you can use the following code:

FieldInfo[] fields = data.GetType()
    .GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
    .Where(f => f.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
    .ToArray();
Jose Rodriguez
  • 9,753
  • 13
  • 36
  • 52