3

I'm studying this simple class and wondering what difference the private set of the Name property actually makes?

If that line simply read public string Name { get; } how would the user's interaction with the class change?

public class Contact2
{
    // Read-only properties. 
    public string Name { get; private set; }
    public string Address { get; }

    // Private constructor. 
    private Contact2(string contactName, string contactAddress)
    {
        Name = contactName;
        Address = contactAddress;               
    }

    // Public factory method. 
    public static Contact2 CreateContact(string name, string address)
    {
        return new Contact2(name, address);
    }
}

They are both read-only properties, and objects of this class can only be constructed via the static method, so does it matter if the set of name is private or not?


EDIT

It is part of this MSDN code:
https://msdn.microsoft.com/en-us/library/bb383979.aspx

whytheq
  • 34,466
  • 65
  • 172
  • 267
  • You cannot modify `Name` from outside but you can still do that from inside. – Tim Schmelter Jul 23 '15 at 09:03
  • @TimSchmelter an aside: if I include `private set;` in a definition of a property, like `public string Name { get; private set; }` then the only way (or at least standard way) it is going to be set is via the constructor? – whytheq Jul 23 '15 at 09:07
  • @whytheq: `private set` means that you can change it from anywhere in the class, not just the constructor. So in theory you could have another method (eg `ChangeAddress`) on the class that changes it. If you want it to be immutable you clearly wouldn't but in other cases you might do that. – Chris Jul 23 '15 at 09:09
  • 2
    It is a slippery slope, the object is immutable to outside code but can still be mutated by the class code. That *might* work, it tends to cause nasty surprises. In the given code snippet, the backing store for the Name property should probably be *readonly*. Programmers hate writing explicit getters too much I guess. – Hans Passant Jul 23 '15 at 09:11
  • @HansPassant: Or assuming the above works `Name` could just lose the private set entirely and work the same as `Address`. I assume this c#6 feature is because we do hate writing getters and setters. :) – Chris Jul 23 '15 at 09:13
  • 1
    @whytheq: After the edit giving the source I wonder what was unclear about "You can declare the set accessor.to be private. The property is only settable within the type, but it is immutable to consumers. You can instead declare only the get accessor, which makes the property immutable everywhere except in the type’s constructor." (from that page). – Chris Jul 23 '15 at 09:16
  • @Chris this is what I'm implying by the question: why bother with the private set at all. Although now I realise there might be reasons. (Fair comment about me not reading the post - apologies - although this discussion has helped me a lot)) – whytheq Jul 23 '15 at 09:16

2 Answers2

5

In C# 6:

public string Name { get; private set; }

Can be set from any method within the class.

public string Address { get; }

Is a read-only property and can only (and must) be set on initialization.

In your code they're functioning the same way, however the read-only property enforces an additional constraint making the property immutable as it can only be set once, whereas you could add a method to the class which mutates Name making the class mutable.

Matthew Mcveigh
  • 5,695
  • 22
  • 22
  • 1
    You may want to add that C# 6 specific answer to [understanding private setters](http://stackoverflow.com/questions/3847832/understanding-private-setters) and vote to close this question as a duplicate of that one. – CodeCaster Jul 23 '15 at 09:10
  • Hi Matthew - thanks - this leads on from your answer (although I suspect it will get severely marked down!)- http://stackoverflow.com/questions/31583814/implementing-read-only-properties-with-get – whytheq Jul 23 '15 at 09:49
  • 1
    @whytheq it looks like that should work but you'll have to be using C# 6 – Matthew Mcveigh Jul 23 '15 at 09:55
3

Getter-only auto properties like public string Name { get; } were not allowed before C# 6.0, so the code would not compile. That's why you needed a private setter before.

See: Getter-only auto-properties.

nodots
  • 1,450
  • 11
  • 19