Is read-only auto-implemented property possible?

C#.NetPropertiesMsdnReadonly

C# Problem Overview


I found a topic on MSDN that talks that yes, this is possible.

I did a test that seems to break this statement:

using System;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Foo f = new Foo("1");
            Console.WriteLine(f.Bar); // prints 1
            f.Test("2");
            Console.WriteLine(f.Bar);// successfully prints 2
        }
    }

    class Foo
    {
        public Foo(string b)
        {
            this.Bar = b;
        }

        public string Bar { get; private set; }

        public void Test(string b)
        {
            // this would be impossible for readonly field!
            // next error would be occur: CS0191 or CS0191
            // A readonly field cannot be assigned to (except in a constructor or a variable initializer)
            this.Bar = b; 
        }
    }
}

Where am I wrong?

C# Solutions


Solution 1 - C#

The answer below was written back in 2010. In C# 6 (released in 2015) you can write read-only automatically-implemented properties:

// This can only be assigned to in a constructor
public int Foo { get; }

You're absolutely right. Properly read-only automatically implemented properties are currently impossible. Making the setter private isn't the same thing, regardless of what some books and MSDN might say :)

If I ruled the world, this would not be the case. When I see some of the language designers at NDC 2010 in June (please come along!) I intend to try to persuade, bribe, cajole and generally make a nuisance of myself until they agree. It's just one wafer-thin feature, after all.

Looking at that MSDN article, the text itself doesn't say that it creates a read-only automatic property. It creates an immutable type using an automatic property, and that's correct. The only problematic bits are the comments saying

// Read-only properties.

... which are definitely wrong. The framework agrees with us:

var prop = typeof(Contact).GetProperty("Name");
Console.WriteLine(prop.CanWrite); // Prints True

Solution 2 - C#

The property is read-only outside the Foo class. I think that's what article is getting at.

But it's not the same as marking a variable with the readonly keyword.

Solution 3 - C#

It's confusing. You should differentiate read-only to the c# readonly (what the keyword means).

  • read-only: they mean that no one outside can write to it directly, only read.
  • C# readonly: you can only write to it in the constructor, then never more.

Solution 4 - C#

No, it's not possible to make an auto-implemented property readonly. For the page you linked:

> with auto-implemented properties, both a get and set accessor are required

A read-only property has NO set accessor.

> A property without a set accessor is considered read-only

Solution 5 - C#

Private set is not the same as readonly.

Similar to methods or fields, the private keyword makes the visibility of the setter available to only the class itself. Other objects cannot use the setter, but methods of the class itself can call it freely. Hence your test code compiles and works fine.

It appears to external objects as a readonly property, but it isn't read-only in the true definition.

Solution 6 - C#

The ReadOnly keyword, in C# and VB, do the same thing when applied to a field. They make it so that field is only assignable during static initialization (if it is marked as a static/shared field) or during the constructor.

C# does not utilize the readonly keyword for anything else.

The ReadOnly keyword in VB takes on a different meaning when applied to a Property. In this case, it simply means that there is no acceptable way to assign to the Public property (internally, the backing field can be modified other internal code, of course).

Solution 7 - C#

It is not possible to create a readonly auto-implemented property. If you try to compile a class with an auto-implemented property you will get this error if it doesn't have both get and set:

>'ProjectName.ClassName.Property.get' must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors.

With the sentence begining with 'Automatically' being the part of the error we are concerned with.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionabatishchevView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#kervinView Answer on Stackoverflow
Solution 3 - C#Samuel CarrijoView Answer on Stackoverflow
Solution 4 - C#Ben VoigtView Answer on Stackoverflow
Solution 5 - C#wompView Answer on Stackoverflow
Solution 6 - C#Scott MarcusView Answer on Stackoverflow
Solution 7 - C#Jose AlavaView Answer on Stackoverflow