Properties
Properties are C#'s built-in mechanism for controlled access to class data — combining the convenience of fields with the validation power of methods.
public class Learner {
// Auto-property — compiler generates a hidden backing field:
public string Name { get; set; }
public int Age { get; set; }
// Read-only outside the class:
public string Course { get; private set; }
// Init-only (C# 9+) — set only during initialisation:
public string Id { get; init; }
public Learner(string id) { Id = id; }
}
var l = new Learner("L001") { Name = "Thandi", Course = "C#" }; // wait, Course has private set
// Better:
var l2 = new Learner("L002");
l2.Name = "Sipho";
l2.Age = 21;
// l2.Course = "Java"; // compile error — private set
Full Property with Validation
When you need to validate or compute a value, write the getter and setter explicitly with a backing field.
public class Learner {
private string _name;
private int _age;
private double _mark;
public string Name {
get => _name;
set {
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Name cannot be empty.");
_name = value.Trim();
}
}
public int Age {
get => _age;
set {
if (value < 15 || value > 80)
throw new ArgumentOutOfRangeException(nameof(Age), $"Age {value} is invalid.");
_age = value;
}
}
public double Mark {
get => _mark;
set {
if (value < 0 || value > 100)
throw new ArgumentOutOfRangeException(nameof(Mark), "Mark must be 0-100.");
_mark = value;
}
}
// Computed property — no backing field:
public string GradeLabel => Mark switch {
>= 80 => "Distinction",
>= 60 => "Merit",
>= 50 => "Pass",
_ => "Not yet competent"
};
}
Using Properties
var l = new Learner();
l.Name = "Thandi"; // calls the setter — validation runs
l.Age = 21;
l.Mark = 74.5;
Console.WriteLine(l.GradeLabel); // Merit
Console.WriteLine(l.Mark); // 74.5
// Setter validation:
try { l.Mark = 150; }
catch (ArgumentOutOfRangeException ex) {
Console.WriteLine(ex.Message); // Mark must be 0-100.
}
Practice Task
Your Turn
Convert your Product class to use full properties: Name validates non-empty, Price (decimal) rejects negatives, Category defaults to "General" if null/empty, Stock (int) rejects negatives. Add a computed IsExpensive bool property returning true if price > 500. Test all validation paths.
Common Mistakes
- Public fields instead of properties — always prefer properties in production C# code.
get; set;when the property should be read-only outside — useget; private set;.- Auto-properties cannot validate — you need a backing field for that.
- Inside a setter, the incoming value is
value— this is an implicit parameter name.
Professional Tip
Properties are one of the most important C# features. They look like fields when you use them but behave like methods — validation runs transparently. This is a genuine ergonomic improvement over Java's explicit getters and setters.
Mini Quiz
What is the implicit parameter name inside a C# property setter?