C# Programming Tutorial 0/45 lessons ~6 min read Lesson 14

    Classes & Objects

    Classes define blueprints; objects are runtime instances with fields, properties, and methods.

    Course progress0%
    Focus
    10 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Introduction

    Classes define blueprints; objects are runtime instances with fields, properties, and methods. C# is single-inheritance for classes but supports multiple interface implementation — the OOP model behind every ASP.NET Core controller, EF entity, and WPF ViewModel.

    Modern C# adds primary constructors (C# 12), required properties, and init accessors for immutable object graphs. Interviewers expect you to explain stack vs heap allocation, object identity, and when to use class vs struct vs record.

    This lesson builds a domain model you will extend through encapsulation, inheritance, and polymorphism in the following modules.

    The story

    An e-commerce platform stores customer profiles with a stable ID, a verified email, and a legal name required for invoicing. Support agents can update an email address through a controlled method that trims whitespace and lowercases the domain — but they cannot assign an empty string or bypass validation by setting a public field directly.

    Classes bundle data and behavior; objects are the live instances created when someone registers on the website.

    Understanding the topic

    Key concepts

    • class keyword defines reference type on heap.
    • new allocates object and calls constructor.
    • Fields store state; properties control access with get/set.
    • this refers to current instance.
    • static members belong to type, not instance.
    • records are reference types with value-based equality by default.
    text
    classDiagram
    class BankAccount {
    -decimal balance
    +Deposit(amount)
    +Withdraw(amount)
    +GetBalance()
    }
    BankAccount --> Transaction : uses

    Step-by-step explanation

    1. Declare class with members; instantiate with new ClassName(args).
    2. GC reclaims unreachable objects — no manual free.
    3. Reference variables alias same object when assigned.
    4. Object initializer syntax: new Customer { Name = "A" }.
    5. Primary constructor parameters can initialize fields/properties.
    6. sealed prevents inheritance; abstract requires subclass.

    Practical code example

    Customer entity with primary constructor, required property, and domain method:

    csharp
    namespace TechLearningPro.Classes;
    public sealed class Customer(string id, string email)
    {
    public string Id { get; } = id;
    public required string LegalName { get; init; }
    public string Email { get; private set; } = email;
    public void UpdateEmail(string newEmail)
    {
    ArgumentException.ThrowIfNullOrWhiteSpace(newEmail);
    Email = newEmail.Trim().ToLowerInvariant();
    }
    }

    Line-by-line code explanation

    • public sealed class Customer(string id, string email) uses a primary constructor (C# 12) to capture constructor parameters.
    • public string Id { get; } exposes a read-only identifier set once at construction.
    • public required string LegalName { get; init; } must be supplied during object initialization.
    • public string Email { get; private set; } = email allows internal updates but not public assignment.
    • UpdateEmail(string newEmail) is the only supported way to change the email address.
    • ArgumentException.ThrowIfNullOrWhiteSpace(newEmail) rejects null, empty, or whitespace-only input.
    • Email = newEmail.Trim().ToLowerInvariant() normalizes the address before storing it.
    • sealed prevents further inheritance — appropriate when the class is a concrete domain entity.

    Key takeaway: Primary constructor (C# 12) reduces boilerplate. required ensures object initializer provides LegalName. Encapsulate mutation in methods.

    Real-world use

    Where you'll use this in production

    • Domain entities in DDD bounded contexts.
    • DTOs and ViewModels in MVC/MVVM apps.
    • Plugin classes loaded via reflection in extensible platforms.
    • Game entities with Update loop methods.

    Best practices

    • Favor immutability with init or record types.
    • Keep fields private; expose properties.
    • Single responsibility per class.
    • Use factory methods for complex construction.
    • Override ToString for debugging; not for production logs of PII.

    Common mistakes

    • Public mutable fields breaking encapsulation.
    • God classes with 50+ members.
    • Confusing class (reference) with struct (value) semantics.
    • Creating objects in tight loops without pooling consideration.

    Advanced interview questions

    Q1BeginnerClass vs object?
    Class is template; object is instance allocated on heap.
    Q2BeginnerWhat is static?
    Member belongs to type; one copy shared; no instance needed.
    Q3IntermediateClass vs struct?
    Class reference type heap; struct value type stack-friendly; choose struct for small immutable data.
    Q4IntermediatePurpose of sealed?
    Prevents further inheritance — safety and optimization hint.
    Q5AdvancedModel immutable Order with line items in C# 12.
    public sealed record Order(string Id, IReadOnlyList Items); init-only collections; AddLine returns new Order via with expression.

    Summary

    Classes define types; objects are instances with identity on the heap. Properties encapsulate state; methods encapsulate behavior. Primary constructors and required/init modernize object creation. Choose class vs struct vs record based on semantics and size. Next: constructors and object initialization.

    Ready to mark this lesson complete?Track your journey across the entire course.