Fields & Properties
How to Store and Control Data in Your Classes
Storing Data in Your Classes
In Lesson 1, we learned about classes. Now let's learn how to store data in them! We use Fields and Properties to hold and control information.
- Fields = The actual data storage (like a box where you keep things)
- Properties = The door to that box with rules about who can open it
Step 1: What is a Field?
A field is a place where you store data inside a class.
Fields are Like Boxes
Each field stores one piece of information:
public class Student
{
// Fields - the data boxes
private string firstName; // Box for first name
private string lastName; // Box for last name
private int age; // Box for age
private string email; // Box for email
}
- string = Text data (like "John")
- int = Whole number (like 25)
- private = Only this class can see the box
Why Make Fields private?
public, anyone can put bad data!
// ❌ BAD - anyone can do this
public class Student
{
public int Age; // Anyone can set age to -5!
}
// Someone can write:
Student s = new Student();
s.Age = -5; // This is bad! Age should be positive
Solution: Make fields private and use Properties to control access!
Step 2: What is a Property?
A property is like a security guard for your field.
Properties Control Access
A property has two parts:
- get - Allows reading the value (like opening the door to look inside)
- set - Allows changing the value (like putting something in the box)
public class Student
{
// Private field (the box)
private int age;
// Public property (the security guard)
public int Age
{
get { return age; } // Let people see the age
set // Let people change the age
{
// But only if the age is valid!
if (value > 0 && value < 120)
age = value;
else
Console.WriteLine("Invalid age!");
}
}
}
Using the Property
Student s = new Student();
// Using the property (calls the setter)
s.Age = 25; // ✅ Works! Age is valid
s.Age = -5; // ❌ Error! "Invalid age!"
// Reading the property (calls the getter)
Console.WriteLine(s.Age); // Output: 25
- ✅ Validation - Check if data is correct
- ✅ Protection - Keep your data safe
- ✅ Control - Decide who can read/write
Step 3: Auto-Implemented Properties (The Easy Way)
When you don't need validation, C# lets you use auto-properties - it's much shorter!
Manual Property (Long Way)
public class Student
{
private string firstName; // Field
public string FirstName // Property
{
get { return firstName; }
set { firstName = value; }
}
}
⚠️ Lot of code for just storing data!
Auto-Property (Short Way)
public class Student
{
// C# creates the hidden field automatically!
public string FirstName { get; set; } // ✅ Clean!
public string LastName { get; set; } // ✅ Clean!
public int Age { get; set; } // ✅ Clean!
}
Different Types of Properties
Read-Only Properties
What: Can only be read, not changed
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
// Read-only - no setter!
public string FullName => $"{FirstName} {LastName}";
}
student.FullName - calculated from other data
Private Setters
What: Everyone can read, but only the class can change
public class BankAccount
{
public decimal Balance { get; private set; }
public void Deposit(decimal amount)
{
if (amount > 0)
Balance += amount; // Only the class can change Balance
}
}
Init-Only Properties (C# 9+)
What: Can be set when created, then never changed
public class Student
{
public int StudentId { get; init; } // Set once
public string Email { get; init; } // Set once
}
// Create and set:
Student s = new Student { StudentId = 1, Email = "john@school.com" };
// ❌ Can't change it later!
// s.StudentId = 2; // Compiler error!
Expression-Bodied Properties
What: Short way to write read-only properties
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
// Expression-bodied property (shorter!)
public string FullName => $"{FirstName} {LastName}";
// Same as writing:
public string FullName2
{
get { return $"{FirstName} {LastName}"; }
}
}
=> means "returns this value"
Real-World Example: Student Class
Let's build a complete Student class with fields and properties:
Student.cs
using System;
public class Student
{
// Private fields (the data storage)
private string firstName;
private string lastName;
private int age;
private int gradeLevel;
// Auto-properties (simple data)
public string Email { get; set; }
public string PhoneNumber { get; set; }
// Manual properties (with validation)
public string FirstName
{
get { return firstName; }
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("First name cannot be empty!");
firstName = value;
}
}
public string LastName
{
get { return lastName; }
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Last name cannot be empty!");
lastName = value;
}
}
public int Age
{
get { return age; }
set
{
if (value < 0 || value > 120)
throw new ArgumentException("Age must be between 0 and 120!");
age = value;
}
}
public int GradeLevel
{
get { return gradeLevel; }
set
{
if (value < 1 || value > 12)
throw new ArgumentException("Grade level must be 1-12!");
gradeLevel = value;
}
}
// Read-only property (calculated)
public string FullName => $"{FirstName} {LastName}";
// Constructor
public Student(string firstName, string lastName, int age, int gradeLevel)
{
FirstName = firstName;
LastName = lastName;
Age = age;
GradeLevel = gradeLevel;
}
// Method to display student info
public void DisplayInfo()
{
Console.WriteLine($"Name: {FullName}");
Console.WriteLine($"Age: {Age}");
Console.WriteLine($"Grade Level: {GradeLevel}");
Console.WriteLine($"Email: {Email}");
Console.WriteLine($"Phone: {PhoneNumber}");
Console.WriteLine();
}
}
Program.cs (Using the Student)
using System;
class Program
{
static void Main()
{
// Create a student using the constructor
Student student1 = new Student("John", "Smith", 15, 10);
student1.Email = "john@school.com";
student1.PhoneNumber = "555-1234";
student1.DisplayInfo();
// Try to set invalid data - see the validation work!
try
{
student1.Age = -5; // ❌ This will throw an error
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
try
{
student1.GradeLevel = 99; // ❌ This will throw an error
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
// Create another student with auto-properties
Student student2 = new Student("Jane", "Doe", 16, 11);
student2.Email = "jane@school.com";
student2.PhoneNumber = "555-5678";
student2.DisplayInfo();
}
}
- ✅ Auto-properties for simple data (Email, Phone)
- ✅ Manual properties with validation (Age, GradeLevel)
- ✅ Read-only property (FullName)
- ✅ Private fields for data storage
When to Use Fields vs Properties
Use Fields When:
- ✅ The data is private (only used inside the class)
- ✅ You need a constant value that never changes
- ✅ The data is readonly (set once in constructor)
public class Employee
{
private string name; // ✅ Private field
private int id; // ✅ Private field
private const double TaxRate = 0.15; // ✅ Constant
}
Use Properties When:
- ✅ The data needs to be public (accessible from outside)
- ✅ You need validation (check the data)
- ✅ The value is calculated from other data
- ✅ You want different read/write permissions
public class Employee
{
public string Name { get; set; } // ✅ Public property
public int ID { get; init; } // ✅ Init-only
public string FullName => $"{Name} (#{ID})"; // ✅ Calculated
}
What You Learned Today
Fields
Private data storage
Properties
Controlled access to data
Auto-Properties
Short way for simple data
Validation
Keep your data safe
Exercise: Create a Product Class
Your Task:
Create a Product class with the following:
Requirements:
-
Fields (private):
name(string)price(decimal)quantity(int)
-
Properties (public):
Name- cannot be emptyPrice- must be greater than 0Quantity- must be 0 or more
-
Auto-property:
Category(string)
More Requirements:
-
Read-only property:
TotalValue- calculates price * quantity
-
Constructor:
- Takes name, price, quantity, category
-
Method:
DisplayInfo()- shows all product details
// Product.cs
using System;
public class Product
{
// Private fields
private string name;
private decimal price;
private int quantity;
// Properties with validation
public string Name
{
get { return name; }
set
{
if (string.IsNullOrWhiteSpace(value))
throw new ArgumentException("Name cannot be empty!");
name = value;
}
}
public decimal Price
{
get { return price; }
set
{
if (value <= 0)
throw new ArgumentException("Price must be greater than 0!");
price = value;
}
}
public int Quantity
{
get { return quantity; }
set
{
if (value < 0)
throw new ArgumentException("Quantity cannot be negative!");
quantity = value;
}
}
// Auto-property
public string Category { get; set; }
// Read-only property (calculated)
public decimal TotalValue => Price * Quantity;
// Constructor
public Product(string name, decimal price, int quantity, string category)
{
Name = name;
Price = price;
Quantity = quantity;
Category = category;
}
// Method to display info
public void DisplayInfo()
{
Console.WriteLine($"📦 Product: {Name}");
Console.WriteLine($"📁 Category: {Category}");
Console.WriteLine($"💰 Price: ${Price:F2}");
Console.WriteLine($"📊 Quantity: {Quantity}");
Console.WriteLine($"💵 Total Value: ${TotalValue:F2}");
Console.WriteLine();
}
}
// Program.cs
class Program
{
static void Main()
{
// Create a product
Product laptop = new Product("Gaming Laptop", 1200.00m, 5, "Electronics");
laptop.DisplayInfo();
// Create another product
Product book = new Product("C# Programming Book", 49.99m, 20, "Books");
book.DisplayInfo();
}
}