【问题标题】:How to find if a member variable is readonly?如何查找成员变量是否为只读?
【发布时间】:2013-03-31 14:14:59
【问题描述】:
class Bla
{
    public readonly int sum;
}

FieldInfo f = type.GetField("sum");
f.??   // what?

如何确定sum 是否为只读?对于属性,我可以通过PropertyInfo.CanWrite 查找成员是否具有写入权限。

【问题讨论】:

    标签: c# .net reflection readonly fieldinfo


    【解决方案1】:

    readonly 表示字段赋值只能发生在字段声明附近或构造函数内部。所以你可以在FieldInfo 上使用IsInitOnly 属性,

    获取一个值,该值指示该字段是否只能在构造函数的主体中设置

    更多详情请见IsInitOnly MSDN article

    FieldInfo f = typeof(Bla).GetField("sum");
    Console.WriteLine(f.IsInitOnly); //return true
    

    注意:您也可以使用IsLiteral 属性来测试该字段是否为编译时间常数。对于readonly 字段,它将返回false,但对于标有const 的字段,它将返回true。

    另一个注意事项:反射不会阻止您写入readonlyprivate 字段(public readonly 也是如此,但我想展示一个更受限制的情况)。所以接下来的代码示例是有效的,不会抛出任何异常:

    class Bla
    {
        //note field is private now
        private readonly int sum = 0;
    }
    

    现在,如果您获取该字段并向其写入值(我使用BindingFlags 获取私有非静态字段,因为默认情况下GetField 不会为私有字段返回FieldInfo

    FieldInfo field = typeof(Bla).GetField("sum", BindingFlags.NonPublic |
                                                  BindingFlags.Instance);
    
    var bla = new Bla();
    field.SetValue(bla, 42);
    
    Console.WriteLine(field.GetValue(bla)); //prints 42
    

    一切正常。只有当字段为const时才会抛出异常。

    【讨论】:

    • 知道NonPublic 标志在这里做什么吗?
    • @nawfal GetField 默认不会返回私有字段。您需要明确设置
    • @哦,是的,我明白了。我没有注意到你关于private 的例子。谢谢
    • +1 表示反射不会阻止您编写 readonly 字段(这完全违反直觉)。
    • @SamGoldberg 我同意这是违反直觉的,但另一方面它允许 ORM 工作,例如,同时仍然有一些很好的编译时检查。
    【解决方案2】:

    f.Attributes 应该包含FieldAttributes.InitOnly

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-09
      • 1970-01-01
      • 2011-03-04
      • 1970-01-01
      • 2012-08-27
      相关资源
      最近更新 更多