51

If both get and set are compulsory in C# automatic properties, why do I have to bother specifying "get; set;" at all?

AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
Ben Aston
  • 53,718
  • 65
  • 205
  • 331

9 Answers9

67

Because you might want a read-only property:

public int Foo { get; private set; }

Or Write-only property:

public int Foo { private get; set; }
Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197
Brian Genisio
  • 47,787
  • 16
  • 124
  • 167
  • 3
    You can also add all sorts of modifiers, like protected etc. – Tigraine Dec 04 '08 at 13:15
  • Yeah, and what other people said... you need a way to distinguish between a field and a property. – Brian Genisio Dec 04 '08 at 13:19
  • 1
    A little side note: there is the concept of readonly fields. The framework will make sure that these are only written once. It is different from private setters or getters which can be written if you have access. – Cristian Libardo Dec 04 '08 at 13:24
  • Also, see my answer, it's about more than access levels, the compiler treats fields and properties differently. – Binary Worrier Dec 04 '08 at 14:08
  • Yes, I agree. See my comment (3rd one down) – Brian Genisio Dec 04 '08 at 14:17
  • changed the selected answer because a later comment more fully answers the question – Ben Aston Dec 04 '08 at 17:46
  • @cristianlibardo: The readonly keyword (which sounds like what you are talking about) is different than a read-only property. – Scott Dorman Dec 04 '08 at 19:16
  • @CristianLibardo: readonly fields can be written to as many times as you like, but it can only be written during the construction phase. (Ie. in a ctor or in a variable initializer.) – Arjan Einbu Jan 14 '09 at 23:30
  • 3
    @BrianGenisio These properties are not really read-only, but rather write-privately, which were close enough until now, however in C# 6.0 (Visual Studio 2015) we have real read-only properties ([as answered here](http://stackoverflow.com/a/27291579/2979473)). Yay! – Robert Synoradzki Dec 05 '14 at 09:30
  • @ensisNoctis Fair enough! It is only read-only from the public interface but you are correct, it is not immutable. – Brian Genisio Dec 10 '14 at 15:23
57

ERROR: A property or indexer may not be passed as an out or ref parameter

If you didn't specify {get; set;} then the compiler wouldn't know if it's a field or a property. This is important becasue while they "look" identical the compiler treats them differently. e.g. Calling "InitAnInt" on the property raises an error.

class Test
{
    public int n;
    public int i { get; set; }
    public void InitAnInt(out int p)
    {
        p = 100;
    }
    public Test()
    {
        InitAnInt(out n); // This is OK
        InitAnInt(out i); // ERROR: A property or indexer may not be passed 
                          // as an out or ref parameter
    }
}

You shouldn't create public fields/Variables on classes, you never know when you'll want to change it to have get & set accessors, and then you don't know what code you're going to break, especially if you have clients that program against your API.

Also you can have different access modifiers for the get & set, e.g. {get; private set;} makes the get public and the the set private to the declaring class.

Binary Worrier
  • 50,774
  • 20
  • 136
  • 184
19

Just thought I would share my findings on this topic.

Coding a property like the following, is a .net 3.0 shortcut call “auto-implemented property”.

public int MyProperty { get; set; }

This saves you some typing. The long way to declare a property is like this:

private int myProperty;
public int MyProperty 
{
  get { return myProperty; }
  set { myProperty = value; } 
}

When you use the “auto-implemented property” the compiler generates the code to wire up the get and set to some “k_BackingField”. Below is the disassembled code using Reflector.

public int MyProperty
{
    [CompilerGenerated]
    get
    {
        return this.<MyProperty>k__BackingField;
    }
    [CompilerGenerated]
    set
    {
        this.<MyProperty>k__BackingField = value;
    }
}

disassembled C# code from IL

Also wires up a method for the setter and getter.

[CompilerGenerated]
public void set_MyProperty(int value)
{
    this.<MyProperty>k__BackingField = value;
}
[CompilerGenerated]
public int get_MyProperty()
{
    return this.<MyProperty>k__BackingField;
}

disassembled C# code from IL

When you declare a read only auto-implemented property, by setting the setter to private:

 public int MyProperty { get; private set; }

All the compiler does flag the "set" as private. The setter and getter method say the same.

public int MyProperty
{
    [CompilerGenerated]
    get
    {
        return this.<MyProperty>k__BackingField;
    }
    private [CompilerGenerated]
    set
    {
        this.<MyProperty>k__BackingField = value;
    }
}

disassembled C# code from IL

So I am not sure why the framework require both the get; and set; on an auto-implemented property. They could have just not written the set and setter method if it was not supplied. But there may be some compiler level issue that makes this difficult, I don't know.

If you look at the long way of declaring a read only property:

public int myProperty = 0;
public int MyProperty
{
    get { return myProperty; }
}  

And then look at the disassembled code. The setter is not there at all.

public int Test2
{
    get
    {
        return this._test;
    }
}

public int get_Test2()
{
    return this._test;
}

disassembled C# code from IL

Ron Todosichuk
  • 274
  • 1
  • 5
  • 5
    The private set method is required with auto-properties because otherwise you'd never be able to set the value to anything, which would be pointless. You can exclude the setter from a non-auto property because the backing field provides a way to change the value internally. – Jeromy Irvine Dec 04 '08 at 17:41
  • Good point, that is correct. Because you do not have a private variable, while using an auto-implemented property, you have know way of setting a value if it was not there. – Ron Todosichuk Dec 04 '08 at 20:10
17

Because you need some way to distinguish it from plain fields.

It's also useful to have different access modifiers, e.g.

public int MyProperty { get; private set; }
Cristian Libardo
  • 9,260
  • 3
  • 35
  • 41
5

The compiler needs to know if you want it to generate a getter and/or a setter, or perhaps are declaring a field.

Kris
  • 40,604
  • 9
  • 72
  • 101
2

Since no one mentioned it... you could make the auto-property virtual and override it:

public virtual int Property { get; set; }

If there was no get/set, how would it be overridden? Note that you are allowed to override the getter and not the setter:

public override int Property { get { return int.MinValue; } }
Community
  • 1
  • 1
Zaid Masud
  • 13,225
  • 9
  • 67
  • 88
2

Also, because ever since C# 6.0 (in Visual Studio 2015, at the time of this answer available in version Ultimate Preview) you may implement a true read-only property:

public string Name { get; }
public string Name { get; } = "This won't change even internally";

... as opposed to currently imperfect workaround with public getter/private setter pair:

public string Name { get; private set; }

public Constructor() { Name="As initialised"; }
public void Method() { Name="This might be changed internally. By mistake. Or not."; }

Example of the above below (compiled and executable online here).

using System;

public class Propertier {
    public string ReadOnlyPlease { get; private set; }

    public Propertier()  { ReadOnlyPlease="As initialised"; }
    public void Method() { ReadOnlyPlease="This might be changed internally"; }
    public override string ToString() { return String.Format("[{0}]",ReadOnlyPlease); }
}

public class Program {
    static void Main() {
        Propertier p=new Propertier();
        Console.WriteLine(p);

//      p.ReadOnlyPlease="Changing externally!";
//      Console.WriteLine(p);

        // error CS0272: The property or indexer `Propertier.ReadOnlyPlease' cannot be used in this context because the set accessor is inaccessible
        // That's good and intended.

        // But...
        p.Method();
        Console.WriteLine(p);
    }
}

Other tasty news about C# 6.0 available as official preview video here.

Robert Synoradzki
  • 1,766
  • 14
  • 20
2

If the property didn't have accessors, how would the compiler separate it from a field? And what would separate it from a field?

Rune Grimstad
  • 35,612
  • 10
  • 61
  • 76
2

Well, obviously you need a way of disambiguating between fields and properties. But are required keywords really necessary? For instance, it's clear that these two declarations are different:

public int Foo;
public int Bar { }

That could work. That is, it's a syntax that a compiler could conceivably make sense of.

But then you get to a situation where an empty block has semantic meaning. That seems precarious.

Robert Rossney
  • 94,622
  • 24
  • 146
  • 218