I'm using reflection to map out objects. These objects are in managed code but I have no visibility into their source code, underlying structure, etc. other than through reflection. The overarching goal of all this is a rudimentary memory map of an object (similar in functionality to SOS.dll DumpObject
and !ObjSize
commands). As such, I'm trying to determine which members are being "double counted" as both a field and a property.
For example:
public class CalendarEntry
{
// private property
private DateTime date { get; set;}
// public field
public string day = "DAY";
}
When mapped shows:
- Fields
- day
- k__BackingField
- Properties
- date
Where as a class like this:
public class CalendarEntry
{
// private field
private DateTime date;
// public field
public string day = "DAY";
// Public property exposes date field safely.
public DateTime Date
{
get
{
return date;
}
set
{
date = value;
}
}
}
When mapped shows:
- Fields
- day
- date
- Properties
- Date
At first glance there's nothing to tell you that the Date
property's "backing field" is the field named date
. I'm trying to avoid counting date twice in this scenario since that will give me a bad memory size approximation.
What's more confusing/complicated is I've come across scenarios where properties don't always have a corresponding field that will be listed through the Type.GetFields()
method so I can't just ignore all properties completely.
Any ideas on how to determine if a field in the collection returned from Type.GetFields()
is essentially the backing field of some corresponding property returned from Type.GetProperties()
?
Edit- I've had trouble determining what conditions a property will not have a corresponding field in listed in the collection returned from Type.GetFields()
. Is anyone familiar with such conditions?
Edit 2- I found a good example of when a property's backing field would not be included in the collection returned from Type.GetFields()
. When looking under the hood of a String you have the following:
- Object contains Property named FirstChar
- Object contains Property named Chars
- Object contains Property named Length
- Object contains Field named m_stringLength
- Object contains Field named m_firstChar
- Object contains Field named Empty
- Object contains Field named TrimHead
- Object contains Field named TrimTail
- Object contains Field named TrimBoth
- Object contains Field named charPtrAlignConst
- Object contains Field named alignConst
The m_firstChar
and m_stringLength
are the backing fields of the Properties FirstChar
and Length
but the actual contents of the string are held in the Chars property. This is an indexed property that can be indexed to return all the chars in the String but I can't find a corresponding field that holds the characters of a string. Any thoughts on why that is? Or how to get the backing field of the indexed property?