If both get and set are compulsory in C# automatic properties, why do I have to bother specifying "get; set;" at all?
Because you might want a read-only property:
public int Foo { get; private set; }
Or Write-only:
public int Foo { private get; set; }
The compiler needs to know if you want it to generate a getter and/or a setter, or perhaps are declaring a field.
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; }
If the property didn't have accessors, how would the compiler separate it from a field? And what would separate it from a field?
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 i)
{
i = 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.
Edit: suggestion withdrawn due to the struct
problem mentioned in the comments.
I don't think there is a satisfactory answer to this. The C# compiler should be enhanced so that it has an option (switched on by default for new projects) such that if you declare a public or protected field that would be visible outside your assembly:
public class C
{
public string S;
}
Then it generates an auto-property. This would not affect private or internal fields, or public fields of internal classes (because other assemblies wouldn't see them). There is no need to allow public/protected fields to exist. Any reasonable book or source of advice will ban you from using them. This is due to the fact that you cannot later change them to properties without breaking binary compatibility between assemblies. With this change, that advice would become irrelevant. A public field would be no problem at all, because it would be identical to an auto-property.
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
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.