In a real city, you wouldn't let anyone slap a -50 on a building's floor count. Buildings need smart specifications that validate themselves. In C#, properties let you control how fields are read and written — they look like fields but act like methods.
A property uses get and setaccessors. The get accessor returns the value; the set accessor assigns it. Inside set, the magic keyword value holds whatever was assigned:
class Building
{
private int floors; // private backing field
public int Floors
{
get { return floors; }
set
{
if (value > 0)
floors = value;
else
Console.WriteLine("Error: Floors must be positive!");
}
}
}
Now building.Floors = -5; won't corrupt your data — the setter rejects the bad input. This is encapsulation in action: hiding the raw field and exposing a controlled interface.
For simple cases where you don't need validation, C# offers auto-properties — the compiler generates the backing field for you:
class Building
{
public string Name { get; set; } // read + write
public DateTime BuiltOn { get; private set; } // read anywhere, write only inside class
}
You can also create computed properties that calculate their value on the fly — no stored field at all. Use expression-bodied syntax for conciseness:
class Building
{
public int Floors { get; set; }
// Computed property — no backing field needed
public bool IsSkyscraper => Floors >= 20;
}
{ get; set; } — auto-property, read and write
{ get; private set; } — readable everywhere, only settable inside the class
{ get; } — read-only property (set only in constructor)
Backing field — the private variable behind a full property
value — the implicit parameter in the set accessor
Expression-bodied property — public int X => expression; (read-only, computed)
Modern C# (9+) also supports init-only setters: { get; init; }. These can be set during object creation (via constructor or object initializer) but become read-only afterward — perfect for immutable data.
class Building
{
public string Name { get; init; } // set once, then locked
}
var b = new Building { Name = "Fortress" };
// b.Name = "Shack"; // ERROR — can't change after init
📋 Instructions
**Smart Buildings!**
1. Create a `Building` class with:
- A `Name` auto-property (`{ get; set; }`, type string)
- A private backing field `private int floors;`
- A `Floors` property with `get` that returns `floors`, and `set` that:
- If `value > 0`, sets `floors = value`
- Otherwise, prints `"Error: Floors must be positive!"`
- A computed property `IsSkyscraper` that returns `true` if `Floors >= 20` (use `=>`)
2. In `Main`:
- Create a `Building`, set `Name = "HQ Tower"`, `Floors = 40`
- Print: `Building: HQ Tower`
- Print: `Floors: 40`
- Print: `Is Skyscraper: True`
- Attempt `Floors = -10` (should print the error)
- Print: `Floors unchanged: 40`
The `Floors` property needs a `get` returning `floors` and a `set` using `if (value > 0)`. For `IsSkyscraper`, use `public bool IsSkyscraper => Floors >= 20;`.