█
LastWrite
  • > Curriculum
  • > Pricing
  • > For Educators
  • > About
  • > Contact
Log InGet Started

Questions, concerns, bug reports, or suggestions? We read every message, write to us at [email protected].

More ways to reach us →
LastWrite

Structured computer science lessons for aspiring developers and security professionals.

[email protected]

(201) 785-7951

Mon–Fri, 9 AM–5 PM EST

Learn

  • Curriculum
  • Pricing

Company

  • About
  • For Educators & Schools
  • Contact Us

Legal

  • Terms of Service
  • Privacy Policy
© 2026 LastWrite. All rights reserved.
Curriculum/Programming Languages/C# and .NET/OOP in C#
55 minIntermediate

OOP in C#

After this lesson, you will be able to: Write C# classes with interfaces, abstract classes, inheritance, polymorphism, access modifiers, and auto-properties.

C# is OOP through and through. Get the patterns right and you'll read .NET source code (which is open) like a book.

Prerequisites:C# Fundamentals

Classes, properties, constructors

Auto-properties cut boilerplate.

tsx
public class User {
// Auto-properties (C# 3+), compiler generates the backing field
public string Name { get; set; } // mutable
public string Email { get; init; } // init-only (C# 9+), set once in init or constructor
public int Age { get; private set; } // mutable internally; readonly from outside
public DateTime CreatedAt { get; } = DateTime.UtcNow; // readonly with default
// Primary constructor (C# 12+)
public User(string name, string email) {
Name = name;
Email = email;
}
public void Birthday() => Age++;
// Override ToString for nice debug output
public override string ToString() => $"{Name} <{Email}>";
}
var alex = new User("Alex", "[email protected]");
alex.Birthday();
Console.WriteLine(alex); // Alex <[email protected]>

Interfaces + abstract classes

Interfaces define contracts; abstract classes share partial impl.

tsx
// Interface (prefer for contracts)
public interface IRepository<T> {
Task<T?> FindByIdAsync(int id);
Task SaveAsync(T item);
}
// Implementation
public class UserRepository : IRepository<User> {
public Task<User?> FindByIdAsync(int id) {
// ... DB lookup
return Task.FromResult<User?>(null);
}
public Task SaveAsync(User user) {
// ... save
return Task.CompletedTask;
}
}
// Abstract class, partial implementation
public abstract class Shape {
public abstract double Area(); // must override
public virtual string Describe() => $"Shape with area {Area()}"; // can override
}
public class Circle : Shape {
public double Radius { get; init; }
public override double Area() => Math.PI * Radius * Radius;
}

Records (C# 9+) — value-semantic classes

Use when modeling data with equality by value.

tsx
// Record: auto ToString, auto Equals (by value), immutable by default
public record User(string Name, string Email, int Age);
var a = new User("Alex", "[email protected]", 30);
var b = new User("Alex", "[email protected]", 30);
Console.WriteLine(a == b); // True (record equality by value!)
Console.WriteLine(a.ToString()); // User { Name = Alex, Email = [email protected], Age = 30 }
// Records support 'with' expressions for non-destructive mutation
var older = a with { Age = 31 }; // new record with Age changed
// Record struct (value type record, C# 10+)
public record struct Point(double X, double Y);

💡 Access modifiers

public: visible everywhere. private: same class only (default for members). protected: class + subclasses. internal: same assembly only (default for top-level types). protected internal: protected OR internal. private protected (C# 7.2+): protected AND internal (same assembly + subclasses).

Properties vs fields

ALWAYS expose properties, not fields. Properties can be virtual, can have logic, can be readonly externally. Private fields backing properties are fine. Public fields are a code smell, refactoring later changes the binary interface. Auto-properties (get; set;) make this almost free.

Common mistakes

Public fields instead of properties (breaks ABI when refactoring). Deep inheritance hierarchies (favor interfaces + composition). Forgetting `override` (the new method shadows instead of overrides, bugs). Mutable records (defeats the value-equality purpose).

Sign in and purchase access to unlock this lesson.

Sign in to purchase
←C# Fundamentals
Back to C# and .NET
C# Type System: Value vs Reference Types→