为什么Type.GetFields()不返回基类中的后备字段?

Cyg*_*gon 7 c# reflection properties backing-field

在C#中,如果使用Type.GetFields()表示派生类的类型,它将返回a)派生类中所有显式声明的字段,b)派生类中自动属性的所有支持字段和c)基础中所有显式声明的字段类.

为什么缺少基类中自动属性的d)支持字段?

例:

public class Base {
    public int Foo { get; set; }
}
public class Derived : Base {
    public int Bar { get; set; }
}
class Program {
    static void Main(string[] args) {
        FieldInfo[] fieldInfos = typeof(Derived).GetFields(
            BindingFlags.Public | BindingFlags.NonPublic |
            BindingFlags.Instance | BindingFlags.FlattenHierarchy
        );
        foreach(FieldInfo fieldInfo in fieldInfos) {
            Console.WriteLine(fieldInfo.Name);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这将只显示Bar的支持字段,而不是Foo.

Cod*_*aos 8

作为背景场的场对反射没有影响.支持字段的唯一相关属性是它们是私有的.

即使您使用,反射函数也不会返回基类的私有成员FlattenHierarchy.您需要在类层次结构上手动循环,并在每个层次上请求私有字段.

我认为这FlattenHierarchy是为了让所有成员都能看到你所看到的类中的代码.因此,基础成员可以由更多派生类中具有相同名称的成员隐藏/隐藏,并且私有成员根本不可见.


Pip*_*per 6

这是使用HashSet的修订版本:

public static FieldInfo[] GetFieldInfosIncludingBaseClasses(Type type, BindingFlags bindingFlags)
{
    FieldInfo[] fieldInfos = type.GetFields(bindingFlags);

    // If this class doesn't have a base, don't waste any time
    if (type.BaseType == typeof(object))
    {
        return fieldInfos;
    }
    else
    {   // Otherwise, collect all types up to the furthest base class
        var currentType = type;
        var fieldComparer = new FieldInfoComparer();
        var fieldInfoList = new HashSet<FieldInfo>(fieldInfos, fieldComparer);
        while (currentType != typeof(object))
        {
            fieldInfos = currentType.GetFields(bindingFlags);
            fieldInfoList.UnionWith(fieldInfos);
            currentType = currentType.BaseType;
        }
        return fieldInfoList.ToArray();
    }
}

private class FieldInfoComparer : IEqualityComparer<FieldInfo>
{
    public bool Equals(FieldInfo x, FieldInfo y)
    {
        return x.DeclaringType == y.DeclaringType && x.Name == y.Name;
    }

    public int GetHashCode(FieldInfo obj)
    {
        return obj.Name.GetHashCode() ^ obj.DeclaringType.GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)