124

I need to implement a read only property on my type. Moreover the value of this property is going to be set in the constructor and it is not going to be changed (I am writing a class that exposes custom routed UI commands for WPF but it does not matter).

I see two ways to do it:

  1. class MyClass
    {
        public readonly object MyProperty = new object();
    }
    
  2. class MyClass
    {
        private readonly object my_property = new object();
        public object MyProperty { get { return my_property; } }
    }
    

With all these FxCop errors saying that I should not have public member variables, it seems that the second one is the right way to do it. Is this correct?

Is there any difference between a get only property and a read only member in this case?

5
  • 46
    I sometimes wish the auto-property syntax included a get; readonly set; option. Commented Oct 12, 2010 at 18:48
  • Possible duplicate of C#, immutability and public readonly fields Commented Feb 22, 2016 at 20:46
  • 4
    @DanBryant There is get; private set;, at least. Commented Feb 7, 2019 at 18:58
  • 3
    @Marc.2377, Actually, they added support for {get;} a short while ago, which resolves this issue. Commented Feb 7, 2019 at 18:59
  • @DanBryant Ah, indeed. I should've read the answers first ;) Commented Feb 7, 2019 at 19:01

9 Answers 9

96

C# 6.0 adds readonly auto properties

public object MyProperty { get; }

So when you don't need to support older compilers you can have a truly readonly property with code that's just as concise as a readonly field.


Versioning:
I think it doesn't make much difference if you are only interested in source compatibility.
Using a property is better for binary compatibility since you can replace it by a property which has a setter without breaking compiled code depending on your library.

Convention:
You are following the convention. In cases like this where the differences between the two possibilities are relatively minor following the convention is better. One case where it might come back to bite you is reflection based code. It might only accept properties and not fields, for example a property editor/viewer.

Serialization
Changing from field to property will probably break a lot of serializers. And AFAIK XmlSerializer does only serialize public properties and not public fields.

Using an Autoproperty
Another common Variation is using an autoproperty with a private setter. While this is short and a property it doesn't enforce the readonlyness. So I prefer the other ones.

Readonly field is selfdocumenting
There is one advantage of the field though:
It makes it clear at a glance at the public interface that it's actually immutable (barring reflection). Whereas in case of a property you can only see that you cannot change it, so you'd have to refer to the documentation or implementation.

But to be honest I use the first one quite often in application code since I'm lazy. In libraries I'm typically more thorough and follow the convention.

Sign up to request clarification or add additional context in comments.

2 Comments

At the moment I'm wishing C# 9 added public type prop => get;
But getter only property and readonly property are completely different. readonly class fields are often used for variables that are initialized during class construction, and will never be changed later on. In short, if you need to ensure your property value will never be changed from the outside, but you need to be able to change it from inside your class code, use a "Get-only" property.
87

The second way is the preferred option.

private readonly int MyVal = 5;

public int MyProp { get { return MyVal;}  }

This will ensure that MyVal can only be assigned at initialization (it can also be set in a constructor).

As you had noted - this way you are not exposing an internal member, allowing you to change the internal implementation in the future.

6 Comments

thanks. the first option also ensures the same. what do you think is the reason why this one is the preferred option?
Is there any reason we shouldn't use public int MyProp { get; private set; }? I know it's not truly readonly, but it's pretty darned close.
@Mike Hofer - Since the int is declared as readonly, you can't change it outside of a constructor.
@Mike Hofer - it really depends on what the intention is... The version I wrote exposes an internal member whose value cannot change after initialization. Yours exposes a member whose value may change after initialization. Really depends on what you want... Mine is readonly, as in, can't be changed at all after init, yours is readonly, as in, by any external class.
@Oded - I can accept that. It's a subtle, but important difference. I can see where it would be useful if you wanted to expose a property that behaved as a constant both internally and externally. Mine certainly wouldn't do that.
|
61

With the introduction of C# 6 (in VS 2015), you can now have get-only automatic properties, in which the implicit backing field is readonly (i.e. values can be assigned in the constructor but not elsewhere):

public string Name { get; }

public Customer(string name)  // Constructor
{
    Name = name;
}

private void SomeFunction()
{
    Name = "Something Else";  // Compile-time error
}

And you can now also initialise properties (with or without a setter) inline:

public string Name { get; } = "Boris";

Referring back to the question, this gives you the advantages of option 2 (public member is a property, not a field) with the brevity of option 1.

Unfortunately, it doesn't provide a guarantee of immutability at the level of the public interface (as in @CodesInChaos's point about self-documentation), because to a consumer of the class, having no setter is indistinguishable from having a private setter.

4 Comments

Good info on new syntax, however, you can reflect and activate a private setter and/or load a value into a backing field (regardless of access modifiers.) It's also possible to distinguish between a private setter and the lack of a setter at run-time using reflection.
@Shaun: good point - there's lots of things you can do with reflection! A number of the possibilities probably go against the intent of the original programmer or even of the language designers, but are you saying readonly fields can be altered using reflection (I don't know the answer, but it seems problematic)?
I wasn't saying that in particular, no, but the answer is: Yes.. you can. gist.github.com/wilson0x4d/a053c0fd57892d357b2c If you think that's problematic, just wait til you learn every operating system on the planet has a mechanism in place where one process can read/write the memory of any other process (given sufficient execution privilege, that is.) This is why no software-based system can ever truly be secure, but, I digress, this doesn't have much do to with the original question :) even if it is interesting!
I'd recommend reading the detailed article as well BillWagner's article
31

In C# 9, Microsoft introduced a new way to have properties set only on initialization using the init accessor, like so:

public class Person
{
  public string FirstName { get; init; }
  public string LastName { get; init; }
}

This way, you can assign values when initializing a new object:

var person = new Person
{
  Firstname = "John",
  LastName = "Doe"
}

But later on, you cannot change it:

person.LastName = "Denver"; // throws a compiler error

2 Comments

The backing fields for init properties are also readonly
You'll need to be using .NET 5 or above, not .NET Framework.
14

You can do this:

public int Property { get { ... } private set { ... } }

3 Comments

Yes, you can, but with this technique you only guarantee that the property cannot be modified by consumers of the class, not that it will remain constant for the lifetime of the object.
Bob: If the property cannot be modified by the consumers of the class then the property is "readOnly" isn't it?
@ElBayames You cannot change the reference, but you can change the internals. Consider when you expose an object with internal state. You can easily just retrieve the object with the exposed get method, then change the internal properties of that object. That is not a true readonly.
7

yet another way (my favorite), starting with C# 6

private readonly int MyVal = 5;

public int MyProp => MyVal;

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties#expression-body-definitions

2 Comments

can't be simplified to one line public int MyProp { get; } = 5; ?
Even simpler: public int MyProp => 5;
5

I agree that the second way is preferable. The only real reason for that preference is the general preference that .NET classes not have public fields. However, if that field is readonly, I can't see how there would be any real objections other than a lack of consistency with other properties. The real difference between a readonly field and get-only property is that the readonly field provides a guarantee that its value will not change over the life of the object and a get-only property does not.

Comments

4

The second method is preferred because of the encapsulation. You can certainly have the readonly field be public, but that goes against C# idioms in which you have data access occur through properties and not fields.

The reasoning behind this is that the property defines a public interface and if the backing implementation to that property changes, you don't end up breaking the rest of the code because the implementation is hidden behind an interface.

Comments

0

Try this:

public string FirstName { get; set; }
public string LastName { get; set; }
public string? Name
    {
        get
        {
            return string.Format("{0} {1}", FirstName, LastName);
        }
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.