michael
michael

Reputation: 15302

Is there any point to marking a private field readonly?

public class Foo
{
    private readonly Bar _bar;
}

public class Foo2
{
    private Bar _bar;
}

I don't see any benefit to marking it as readonly. It's private and if I try do something internally to modify it it's me being dumb since I know how I want my class to behave? So, what's the point? I don't think there is any performance gain here, so that can't be it.

Upvotes: 1

Views: 426

Answers (6)

supercat
supercat

Reputation: 81327

Suppose a class is supposed to hold a changeable set of T's, and it has a private field T[] theArray. There are a number of ways the class could be set up:

  1. That field could be an mutable reference to an array that will never be changed; changes to the list would be accomplished by creating a new array of appropriate size, copying data to it, modifying it as appropriate, and then storing a reference to the new array into the field. Note that the class may inexpensively expose read-only snapshots of the array contents by wrapping the array in a `ReadOnlyCollection`; creation of a snapshot would not require copying the array.
  2. That field could be a mutable reference to a mutable array. Most updates would be done by mutating an existing array, but updates that would go beyond the end of the array would create a new one with elements copied from the old. This is how `List` works. Note that wrapping the array in a `ReadOnlyCollection` would likely yield something that would behave as a read-only view of live data for awhile, but may at some arbitrary future time become a snapshot of the data as of that moment.
  3. That field could be an immutable reference to a mutable array, if the array is either large enough to hold everything that will ever be added. Not likely with a variable-length list, but in some applications it may be reasonable to pre-specify and pre-allocate space for a maximum item count. In this scenario, wrapping the array in a `ReadOnlyCollection` would yield a live view of its state.

The three different approaches have different implications for things like thread-safety. The first can be made thread-safe if the readref-copy-modify-writeref sequence is placed within an Interlocked.CompareExchange loop. The last may be made thread-safe by making individual element writes thread-safe. The second one, however, may only be made thread-safe by at minimum either having all write operations share a lock which is common to the list as a whole and requiring readers to double-check their operations to ensure consistency, or else requiring that all read and write access must go through a common lock.

Upvotes: 1

Michael Paulukonis
Michael Paulukonis

Reputation: 9100

It's private and if I try do something internally to modify it it's me being dumb since I know how I want my class to behave?

If you are the one and only person who will, in the history of the project, ever look at or modify the source code and you have a perfect memory, well, then yeah. No need for comments or other programming conventions. Just cowboy it.

Otherwise, use of conventions to (re)enforce intention is not a bad idea.

Upvotes: 0

myermian
myermian

Reputation: 32525

You're right, there isn't a performance gain. However, there are key differences here:

If you're intention is to create a class where you don't try to modify _bar it really should be a readonly field. There are 2 things I can see here:

  1. Readonly fields can only be initialized inline or during construction (safety).
  2. It guards against other programmers coming along and thinking "Oh, it's not read-only. I can modify it."

Now, it should NOT be readonly if you plan to keep it null until another method is called to initialize it. But, for that I'd look at Lazy<T>.


Essentially, it's your call. If you truly are going to be the ONLY one modifying this class I'd still say follow those rules. It's the best-practice way of doing it. :)

Upvotes: 2

Andy Thomas
Andy Thomas

Reputation: 86509

At the time you wrote this class, you know how you want it to behave.

But:

  • You might make a mistake as you're first writing the class.
  • You might not remember your intentions when you come back to modify the class later.
  • Another programmer may not know your intentions when they modify the class later.

Your declaration allows the compiler to verify that your intentions are satisfied, cheaply and repeatedly. And it communicates to you and others what your intentions were.

Upvotes: 4

Brad Christie
Brad Christie

Reputation: 101614

Readonly is good if you want to assign it on instantiation, but don't want it to be alterable. A good scenario I can think of is perhaps a database class with a username/password.

public MyClass(string user, string password){
  this.username = username;
  this.password = password;
  this.connect();
}

With the assumption that the connection is kept throughout the duration the object is alive, it may make sense to store this information for reference but prevent future alterations once the connection is established.

Upvotes: 1

SLaks
SLaks

Reputation: 888205

It's always nice to have the compiler prevent you from being dumb.

It's especially nice to have the compiler prevent other people from being dumb, even if they're not familiar with the codebase.

It also serves to tell other people reading your code that the field will never change

Upvotes: 19

Related Questions