Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can I change a private static readonly field but not a public one?

having code like this:

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

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

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

Why can I change a private static readonly field but not a public one?

PS: of course I am using properties.

like image 422
cfischer Avatar asked Dec 04 '22 15:12

cfischer


2 Answers

In your first example, you are changing it in the static constructor, which is allowed, if you changed it in any other static method/property, it would be a compiler error.

In your second example, you are attempting to change a static readonly member in a non-static constructor, which isn't allowed.

You can only change static readonly members in the static constructor. Think of it this way, the static constructor runs once, and after that for each instance the instance constructor is invoked. The property wouldn't be very readonly if every instance could change it.

You can, of course, change non-static readonly instance members in the constructor:

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;  
}

Also, I'm confused by your "PS: of course I am using properties". Properties cannot be declared readonly, if you wanted these to be properties and to be readonly-ish, you'd need to make them private set - unless of course you are using a backing field. The main reason I bring this up is because using a property with a private set would allow you to do what your code is trying to do, as the class itself can change the property (static or instance) in any method or constructor, but code outside of the class can not.

// public getters, private setters...
public static bool MaximumRecipientsReached { get; private set; }
public static IList<EmailAddress> Contacts { get; private set; }
like image 139
James Michael Hare Avatar answered Dec 10 '22 10:12

James Michael Hare


It has nothing to do with public vs. private, but instead static vs. non-static constructors.

If you try to set a static readonly item in a non-static constructor (as in your second case), the compiler complains:

A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)

This is because static members are initialized on first access of the type, which could be before any regular constructors are even called. It makes no sense to have static readonly members modifiable from instance constructors, hence the compiler guards against it.

Simply either make the relevant member non-static or put the initialization into the static constructor.

like image 20
Adam Houldsworth Avatar answered Dec 10 '22 09:12

Adam Houldsworth