Properties are the idiomatic public face of C# objects and are what serializers and frameworks bind to.
A property looks like a field to callers but runs accessor code. The common form is the auto-property: public string Name { get; set; }, for which the compiler creates a hidden backing field.
Variations:
{ get; private set; }lets everyone read but only the class write.{ get; init; }can only be set in a constructor or an object initializer:new Person { Name = "Ada" }. After that the object is immutable from outside.required(C# 11) forces callers to set the property in the initializer, a compile-time check.- A computed property has only a getter:
public int Age => DateTime.Today.Year - BirthYear;. - Default values:
public List<string> Tags { get; set; } = [];.
When a setter needs validation, write the accessor yourself. C# 14 adds the field keyword, which refers to the compiler-generated backing field so you don't need to declare one:
public string Name { get; set => field = value.Trim(); }Inside a setter, value is the incoming value.
Object initializers run right after the constructor and set properties by name, so a class with sensible defaults and init properties is often nicer than a constructor with many parameters. Properties also appear in interfaces, are discovered by serializers like System.Text.Json, and by data binding, which is why public data should be properties, not fields.
Example
var p = new Person { Name = " Ada ", BirthYear = 1815 };
p.Tags.Add("math");
Console.WriteLine($"[{p.Name}] {p.Tags.Count}"); // [Ada] 1
Console.WriteLine(p.Age > 200); // True
// p.BirthYear = 1900; // error: init-only
class Person
{
public required string Name
{
get;
set => field = value.Trim(); // C# 14 'field' keyword
}
public int BirthYear { get; init; }
public int Age => DateTime.Today.Year - BirthYear;
public List<string> Tags { get; } = [];
}Remember
- Auto-properties { get; set; } generate the backing field
- init and required give safe, readable object initializers
- Computed properties use => with only a getter
- Use properties, not public fields, for public data
Watch out for
- Writing a setter that assigns the property itself (Name = value), which recurses forever.