33

Are these the same?

public string MyProp { get; }

vs.

public string MyProp { get; private set; }

I mean in both versions the property can be set in its own class but is readonly for other classes?

5
  • 1
    The first is readonly inside the class also.
    – Dennis_E
    Jan 27, 2016 at 11:10
  • 2
    Error will appear for the first one. Try it.
    – Orel Eraki
    Jan 27, 2016 at 11:11
  • 7
    @OrelEraki Not for C# 6.0. The first one is example for read-only automatically-implemented properties. You can only set it's initial value and can't change it. But, you can change the second one inside the class Jan 27, 2016 at 11:11
  • 2
    For property without setter you can only set value from constructor. While private setter can be used by any method to change value. Property with getter-only is a kind of readonly (immutable) property, you set it once and forget (as you can't change it later).
    – Sinatr
    Jan 27, 2016 at 11:19
  • It's a kind of a funny question. What is the difference between a readonly property and one with a private setter? The first is read only, the second can only be set privately. I mean, this is what the code says and what it is, so ... what exactly is the question? Ok, the first one is a new syntax. This would be a completely different question about this syntax. Jan 27, 2016 at 11:57

5 Answers 5

47

public string MyProp { get; } - This is introduced in C# 6.0. And such properties are called read-only auto-properties. Assignments to such members can only occur as part of the declaration or in a constructor in the same class. You can read detailed explanation about it in that MSDN article or in Jon Skeet blog. As explained in that article, such property solves four problem automatically:

  • A read-only-defined backing field
  • Initialization of the backing field from within the constructor
  • Explicit implementation of the property (rather than using an auto-property)
  • An explicit getter implementation that returns the backing field

public string MyProp { get; private set; } - This means that the property is read-only in the outside of this class, but you can change it's value inside of this class.

By the way, you can set read-only auto-properties value using new auto-initialize syntax which is again introduced in C# 6.0:

public string MyProp { get; } = "You cannot change me";

It is equal to this code for the previous versions of C#:

private readonly string myProp = "You cannot change me"
public string MyProp { get { return myProp ; } }

Or, this in C# 6.0:

public string MyProp { get; }
protected MyClass(string myProp, ...)
{
    this.MyProp = myProp;
    ...
}

is equal to this in the previous versions:

private readonly string myProp;
public string MyProp { get { return myProp; } }
protected MyClass(string myProp, ...)
{
    this.myProp = myProp;
    ...
}
8
  • For the first one you can set the initial value only in the constructor in C# 6. Jan 27, 2016 at 11:32
  • @ChocapicSz in C#6?? No, you are not right. C sharp 6.0 will handle this for you. Jan 27, 2016 at 11:32
  • @ChocapicSz: Farhad's sample is a setting value in ctor. This is just another form of syntax.
    – Dennis
    Jan 27, 2016 at 11:34
  • @Farhad Jabiyev: Well, I've tested it and it cannot be set from elsewhere than the constructor. Jan 27, 2016 at 11:37
  • @ChocapicSz It means that msdn is not right: msdn.microsoft.com/en-gb/magazine/dn802602.aspx Jan 27, 2016 at 11:39
1

In the first one no-one can set the properties value, in the second case at least the class itself can change it. Having said this only the first one is a real "read-only"-property.

However consider combining it with a readonly-backend-field:

private readonly string field;
public string MyProp { get { return this.field; } }

Now any attemp to change the value of either the property itself or the backing-field will fail. This is identical to the syntax introduced in C#6 where the baking-field is automatically added to be reradonly:

public string MyProp { get; }

However as you already assumed for other classes both properties work same, meaning are not ment to be modified in any way.

0
1

In C# 6.0:

public class MyClass
{
    public int MyProp1 { get; }
    public int MyProp2 { get; private set; }

    public MyClass()
    {
        // OK
        MyProp1 = 1;
        // OK
        MyProp2 = 2;
    }

    public void MyMethod()
    {
        // Error CS0200  Property or indexer 'MyClass.MyProp1' cannot be assigned to --it is read only
        MyProp1 = 1;
        // OK
        MyProp2 = 2;
    }
}

In earlier versions of C# the first property does not even compile for this reason:

Error 1 'MyClass.MyProp1.get' must declare a body because it is not marked abstract or extern. Automatically implemented properties must define both get and set accessors.

1
  • 1
    You don't use C# 6.0 (as OP seems to), therefore you get this error.
    – Sinatr
    Jan 27, 2016 at 11:21
1

Values of these properties could be defined inside constructor only:

// C#, all versions
private readonly int _foo;
public int Foo
{
    get { return _foo; }
}

// C#, version 6+
// actually, this is the same as above, but backing field is generated 
// for you by compiler
public int Foo { get; }

Note, that if you know the name of backing field, you can change its value through reflection, thus, this will change result of property getter, but this code will fail, because there is no setter:

typeof(SomeType).GetProperty("Foo").SetValue(bar, 1)

Value of this property could be defined inside any method of declaring type, but also one can easily change it using reflection, without knowledge about backing field, because there is setter:

// this will work fine: typeof(SomeType).GetProperty("Foo").SetValue(bar, 1)
public int Foo { get; private set; }

In other words: the main difference, that first one has get-method only, while the second one has both get- and set- methods.

0

Case 1: With no setter, an auto-implemented property can only be set while declaring the property or inside the constructor as a backing property is created. Therefore, acting as a read-only field.
Case 2: With no setter, a property that is not auto-implemented, can only be set while declaring the property as no backing field is created.
Case 3: With a private setter, a property can be set anywhere inside the class.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.