$ dotnet run3086getheapt → Thermostat object_target20Floor · hidden field0set1var t = new Thermostat();2t.Target = 24;3t.Target = 99;4Console.WriteLine(t.Target);5Console.WriteLine(t.Fahrenheit);1class Thermostat {2 int _target = 20;3 public int Target {4 get => _target;5 set => _target =6 Math.Clamp(value, 5, 30);7 }8 public int Fahrenheit =>9 _target * 9 / 5 + 32;10 public int Floor { get; set; }11}new249930308650CS0200
Front row: the code in Program.csBack row: get, the object on the heap, set, and the consoleTokens: values moving through the accessorsFront row: the two parts of Program.cs, the statements that use a Thermostat and the class itself. Back row: the console, the get accessor, the heap holding the object's _target field and Floor's hidden field, and the set accessor. Writes go through set, which clamps 99 to 30; reads come out through get; Fahrenheit is worked out on every read (86) and has no set, so writing it is error CS0200.

Fields and properties

  1. A class keeps its data in fields. Thermostat has one field, _target, which starts at 20. It has no access modifier, so it is private: only code inside the class can read or write it.

Run: set and get

Kinds of property

What happens

// step 1/9 · field
class Thermostat {
  int _target = 20;      // field, starts at 20

no public, no private written → class members are private by default
outside code cannot touch _target directly

The program is real C#: put the five statements and then the class in Program.cs, and dotnet run prints 30 and 86. In one file, top-level statements must come before any class. Under the hood the compiler turns the accessors into two methods, get_Target and set_Target(int value), which is why reading or writing a property can run code.