【问题标题】:Why can I change a private static readonly field but not a public one?为什么我可以更改私有静态只读字段但不能更改公共字段?
【发布时间】:2012-07-05 13:41:06
【问题描述】:

有这样的代码:

    public static readonly bool MaximumRecipientsReached;
    private static readonly IList<EmailAddress> Contacts;

    static AdditionalRecipient()
    {
        Contacts = AnotherClass.Contacts; //works
    }

    public AdditionalRecipient()
    {
        MaximumRecipientsReached = true; //works not
    }

为什么我可以更改私有静态只读字段但不能更改公共字段?

PS:我当然是在使用属性。

【问题讨论】:

  • 您收到的错误信息是什么?

标签: c# .net constructor readonly static-constructor


【解决方案1】:

在您的第一个示例中,您正在静态构造函数中更改它,这是允许的,如果您在任何其他静态方法/属性中更改它,这将是编译器错误。

在您的第二个示例中,您试图在非静态构造函数中更改 static readonly 成员,这是不允许的。

您只能更改static 构造函数中的static readonly 成员。这样想,static 构造函数运行一次,然后为每个实例调用实例构造函数。如果每个实例都可以更改该属性,则该属性不会非常 readonly

当然,您可以在构造函数中更改非static readonly 实例成员:

public static readonly bool MaximumRecipientsReached = false;
public readonly bool MyInstanceReadonly = false;

static AdditionalRecipient()
{
    // static readonly can only be altered in static constructor
    MaximumRecipientsReached = true; 
}

public AdditionalRecipient()
{
    // instance readonly can be altered in instance constructor
    MyInstanceReadonly = true;  
}

另外,我对您的“PS:我当然在使用属性”感到困惑。不能将属性声明为readonly,如果您希望这些是属性并成为readonly-ish,则需要将它们设为private set - 当然除非您使用支持字段。我提出这个的主要原因是因为使用带有私有集的属性将允许您执行代码尝试执行的操作,因为类本身可以更改任何方法或构造函数中的属性(静态或实例),但代码课外不能。

// public getters, private setters...
public static bool MaximumRecipientsReached { get; private set; }
public static IList<EmailAddress> Contacts { get; private set; }

【讨论】:

  • @ChristianFischer:任何时候,这就是我们在这里的目的 ;-)
【解决方案2】:

这与公共与私有无关,而是静态与非静态构造函数。

如果您尝试在非静态构造函数中设置静态只读项(如您的第二种情况),编译器会抱怨:

不能将静态只读字段分配给(静态只读字段除外) 构造函数或变量初始化器)

这是因为静态成员在第一次访问该类型时被初始化,这可能在任何常规构造函数被调用之前。从实例构造函数中修改静态只读成员是没有意义的,因此编译器会防范它。

只需将相关成员设为非静态或将初始化放入静态构造函数即可。

【讨论】:

    【解决方案3】:

    MaximumRecipientsReached 是只读静态的,您正在尝试从非静态构造函数中设置它。您只能在静态构造函数中设置它。

    【讨论】:

      【解决方案4】:

      这是因为静态构造函数只能与其他静态成员一起使用,而非静态构造函数需要实例化对象。因此,如果您实例化该类但该类具有静态构造函数,则该构造函数将永远不会被调用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-08
        • 2012-01-06
        • 2019-06-20
        • 2014-09-09
        • 1970-01-01
        • 1970-01-01
        • 2010-11-26
        • 2018-06-30
        相关资源
        最近更新 更多