33

Are there any differences between the readonly modifier and get-only properties?

Example:

public class GetOnly
{
    public string MyProp { get; }
}

public class ReadOnly
{
    public readonly string MyProp;
}

Bonus: is there a way to make an interface that works with both? (to use with generics)

public interface ISomething
{
    public string MyProp { get; }
}

public class GetOnly : ISomething
{
    public string MyProp { get; }
}

public class ReadOnly : ISomething // Cannot implement
{
    public readonly string MyProp;
}

Many thanks in advance!

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
robjam
  • 969
  • 1
  • 11
  • 24

4 Answers4

50

You're fundamentally misunderstanding the meaning of both of those definitions. Only exposing the getter says nothing about whether or not a value is read-only.

While in this trivial example:

public class GetOnly
{
    public string MyProp { get; }
}

We can say that MyProp will never change its value, we cannot always say that a getter-only property will not have its value changed. An example of this is a situation where we cannot see the implementation of GetOnly, and only know about the public definition - For example, if you were working with a closed-source third party library.

A clearer example is this:

public interface ISomething
{
    string MyProp { get; }
}

This interface does not say that MyProp is read-only. It says that you cannot change the property. It says nothing about the behavior of the property. Even worse, it only says you cannot change the property when explicitly casting as ISomething.

It's entirely possible to implement the interface like so (even though the interface only exposes the getter):

public class GetOnly : ISomething
{
    public string MyProp { get; set; }
}

readonly is a modifier which explicitly enforces the fact that the value will not ever change, except in the declaration or constructor (barring workarounds like reflection).

However, readonly cannot work on properties, as properties are simply syntactic sugar for get/set methods. Further, interfaces only define methods, and as such you cannot define fields (and by extension, readonly fields).

So to answer your question: Yes, they are worlds apart, and are only similar on the surface.

Rob
  • 26,989
  • 16
  • 82
  • 98
24

At first glance the property and the field are functionally equivalent and for the normal use cases of storing data and passing it around there is not much difference in using them.

But you already seem to have found an important issue: Only properties can be part of an interface.

is there a way to make an interface that works with both?

No.

In addition, many APIs that rely on reflection (EF, Serialization) specifically look for properties.

H H
  • 263,252
  • 30
  • 330
  • 514
  • Excellent! I was looking at seeing which one would be lighter in memory and ran into this trying to make things more DRY. – robjam May 28 '16 at 08:23
  • @robjam if you consider using readonly variables instead of get only properties, you should consider using no methods at all and just have a static void main (get the sarcasm?). A get only property is a private readonly field and a public void that returns the value. Nothing else. - http://tryroslyn.azurewebsites.net/#K4Zwlgdg5gBAygTxAFwKYFsB0BhA9gG31QGNkxcIRMBxVCVAJzGIG4AoUSWRFDTAGUgBHdp2jwkadOzYAHYACN8zGMXwBDECBjYYAbzZsYxmPKUrIyGAA99UVMhYBfNk6A== – Mafii May 30 '16 at 07:07
  • You forgot 2 important points: 1) properties can be part not only of an interface, but also of a base class, and can be overridden in a hierarchical chain from class to class. 2) Only properties can be use as sources in a WPF binding. – Massimiliano Kraus Jun 13 '16 at 14:00
  • overriding DOES apply to read-only stuff. I can create a read-only `{ get; }` property in a base class and make it virtual. A child class DO can override it, maybe assigning a different constant value in his own constructor, or even changing the whole logic, creating a private field and doing: `get { return _privateField; }` leaving the field non read-only and so changeable inside the class. What do you mean by "WPF is just another of those API"? It's the prince framework to build desktop-app in Windows, so that's not a difference that you can ignore so easily... o.O' – Massimiliano Kraus Jun 13 '16 at 14:28
  • There's another minor advantage of using a getter - you can easily put a breakpoint on it if you need to see when it's being requested. Minor, but I've used that when I can't work out how to add a custom breakpoint. – GilesDMiddleton Feb 23 '23 at 09:23
2

In the following part:

public class GetOnly
{
    public string MyProp {get; }
}

MyProp is a property. However, in this part:

public class ReadOnly
{
    public readonly string MyProp;
}

MyProp is a field. These are two different things.

is there a way to make an interface that works with both?

No. Only properties can be put into interfaces. Fields cannot.

Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62
2

One is a field (readonly); the other is a property. Interfaces cannot define fields, only properties, methods, indexers and events.

Both can only be assigned via constructor or field initialization, and cannot be changed thereafter.

CoolBots
  • 4,770
  • 2
  • 16
  • 30
  • @HenkHolterman I modified my answer (in regards to `private set`) based on your response. Thank you! – CoolBots May 30 '16 at 13:27