Intermediate · Classes and objects · topic 15 of 43 · 30 min
Properties: get, set, init and required
Explanation
Why not public fields?
With a public field, anyone can write account.Balance = -50000; and nothing stops them. A property puts a small gate in front of the data. Callers still write account.Balance, but your code decides what is allowed. You can also change the inside later without breaking the callers.
Auto-properties
var c = new Customer { Name = "Asha", Age = 21 };
Console.WriteLine($"{c.Name}, {c.City}, {c.Age}"); // Asha, Unknown, 21
class Customer
{
public string Name { get; set; } = "";
public string City { get; set; } = "Unknown"; // default value
public int Age { get; set; }
}A full property with validation
var p = new Product();
p.Price = 250m; // OK
p.Price = -10m; // throws ArgumentException
class Product
{
private decimal _price; // the backing field
public decimal Price
{
get => _price;
set
{
if (value < 0)
throw new ArgumentException("Price cannot be negative");
_price = value;
}
}
}C# 14 (with .NET 10) adds the field keyword, which lets a property use its hidden backing field directly so you do not have to declare _price yourself. The classic form above works in every version and is what you will see in most existing code.
Read-only and private set
class BankAccount
{
public string AccountNo { get; } // read-only: set only in the constructor
public decimal Balance { get; private set; } // anyone reads, only this class writes
public BankAccount(string accountNo) => AccountNo = accountNo;
public void Deposit(decimal amount)
{
if (amount <= 0) throw new ArgumentException("Deposit must be positive");
Balance += amount;
}
}init: set once, while creating
var o = new Order { OrderNo = 1001, Customer = "Ravi" }; // OK
// o.OrderNo = 2002; // error CS8852: init-only property
class Order
{
public int OrderNo { get; init; }
public string Customer { get; init; } = "";
}required: callers must set it
var ok = new Passenger { Name = "Meena", Age = 34 };
// var bad = new Passenger { Name = "Meena" }; // error: required member 'Age' must be set
class Passenger
{
public required string Name { get; init; }
public required int Age { get; init; }
public string? Berth { get; init; }
}Computed properties
class CartLine
{
public decimal Price { get; init; }
public int Qty { get; init; }
public decimal Total => Price * Qty; // calculated each time it is read
}| You write | Read outside? | Write outside? |
|---|---|---|
| { get; set; } | Yes | Yes, any time |
| { get; private set; } | Yes | No (only inside the class) |
| { get; } | Yes | No (only in the constructor) |
| { get; init; } | Yes | Only in the object initializer / constructor |
| required ... { get; init; } | Yes | Must be set in the object initializer |
| => expression | Yes | No (computed) |
Common mistakes and fixes
- A property that calls itself: public int Age { get => Age; set => Age = value; } recurses forever and crashes with StackOverflowException. Use a separate backing field or an auto-property.
- Making every property { get; set; }: think about who should change each value. Prefer private set, init or get-only where you can.
- Putting slow work (database calls) inside a getter: callers expect properties to be quick. Use a method like LoadOrders() instead.
- Non-nullable string properties without a value: warning CS8618. Give a default (= ""), set it in the constructor, or mark it required.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Properties: get, set, init and required · 1/7
In this lesson you will expose data safely with properties.
Prefer a video by a teacher? Find free videos on “C# properties get set init required auto properties tutorial” on YouTube ↗
In real life: Validating a PIN code in a delivery address
Indian PIN codes have exactly 6 digits and do not start with 0. A courier company's address class checks this in the property setter, so a bad PIN can never be stored, no matter which screen or API sets it.
var addr = new Address { Line1 = "12 MG Road", City = "Indore" };
addr.Pin = "452001";
Console.WriteLine($"{addr.Line1}, {addr.City} - {addr.Pin}");
try { addr.Pin = "0123"; }
catch (ArgumentException ex) { Console.WriteLine(ex.Message); }
class Address
{
public required string Line1 { get; init; }
public required string City { get; init; }
private string _pin = "";
public string Pin
{
get => _pin;
set
{
if (value.Length != 6 || value[0] == '0' || !value.All(char.IsDigit))
throw new ArgumentException($"Invalid PIN code: {value}");
_pin = value;
}
}
}Practice (0/4 done)
Inside a set accessor, what holds the value being assigned?
public decimal Balance { get; private set; } Which code can change Balance?
class T { public int Id { get; init; } } var t = new T { Id = 5 }; t.Id = 6; What happens?
Write a class MobileRecharge with: required init property Number (string), a Plan property (decimal) whose setter rejects values below 10 or above 5000 with ArgumentException, and a computed property WithGst that returns Plan * 1.18m. Create one object and print WithGst.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Access modifiers, static members and encapsulationClasses and objects · same module
- Structs, value types and reference typesClasses and objects · same module
- Classes and objectsKotlin and Android App Development · Classes, objects and collections
- Dataclasses and propertiesPython Programming · Object-oriented programming
- ClassesJavaScript Programming (language in depth) · Scope, this, prototypes and classes
- Classes and objectsPython Programming · Object-oriented programming
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Why are properties preferred over public fields?
Answer: They let the class control and validate access, and change internals later
Properties are a controlled gate to the data.
What does required mean on a property?
Answer: The object initializer must set it, or the code does not compile
required is checked by the compiler at the point of creation.
What happens with: public int Age { get => Age; }
Answer: StackOverflowException when read, because the getter calls itself
The getter reads Age, which calls the getter again, forever.
public decimal Total => Price * Qty; What kind of property is this?
Answer: A computed, read-only property
An expression-bodied get-only property calculates its value on every read.
Which accessor allows setting only during object creation?
Answer: init
init (C# 9) is for set-once properties.
What does private set on a property do?Related
Answer: Allows reading from outside but changing only inside the class
The getter stays public; the setter is private.
From Classes and objects
How do you read a @property called total on an object item?Related
Answer: item.total
A property is read like an attribute, without brackets.
What makes a class field private?Related
Which line correctly sets an attribute inside __init__?Related
Answer: self.name = name
Attributes are stored on the object with self.attribute = value.
From Classes and objects
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “Classes and objects” before its exam: Access modifiers, static members and encapsulation, Structs, value types and reference types.
- Module 4 exam: Classes and objects · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
- Then the next module, Inheritance, interfaces and records. 43 topics left in the course before the final exam.