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

    Abstraction

    Abstraction hides complexity behind simplified models — you call TransferMoney without knowing ledger SQL details.

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

    Introduction

    Abstraction hides complexity behind simplified models — you call TransferMoney without knowing ledger SQL details. Abstract classes and interfaces are C# abstraction tools; higher-level patterns include repository, facade, and gateway abstractions over HTTP and databases.

    Interviewers distinguish abstraction from encapsulation: abstraction is about what is exposed conceptually; encapsulation is about hiding how internally. Both appear in layered architecture discussions.

    This lesson builds abstract repositories and services mirroring real ASP.NET Core layering.

    The story

    A SaaS CRM registers new customers without knowing whether they are stored in PostgreSQL, SQL Server, or an in-memory database during demos. The CustomerService depends on ICustomerRepository — an abstraction — while an infrastructure project supplies the EF Core implementation.

    That separation is what lets teams test business logic with a fake repository and swap databases without touching registration code.

    Understanding the topic

    Key concepts

    • Abstraction focuses on essential behavior, hides implementation.
    • abstract class defines partial contract + shared code.
    • interface defines pure contract.
    • Layered architecture abstracts data access from business logic.
    • Dependency inversion: high-level modules depend on abstractions.
    • Leaky abstraction exposes internals — avoid in public APIs.

    Step-by-step explanation

    1. Define IRepository with domain-meaningful methods.
    2. Business services depend on IRepository, not SqlConnection.
    3. Infrastructure project implements interfaces with EF Core.
    4. Abstract class TemplateMethod defines algorithm skeleton.
    5. Consumers see simplified API; complexity in implementation.
    6. Tests substitute fake implementations of abstractions.

    Practical code example

    Abstract repository contract decoupling domain from EF Core:

    csharp
    namespace TechLearningPro.Abstraction;
    public interface ICustomerRepository
    {
    Task<Customer?> FindByIdAsync(Guid id, CancellationToken ct);
    Task AddAsync(Customer customer, CancellationToken ct);
    Task SaveChangesAsync(CancellationToken ct);
    }
    public sealed record Customer(Guid Id, string Email, string Name);
    public sealed class CustomerService(ICustomerRepository repo)
    {
    public async Task RegisterAsync(string email, string name, CancellationToken ct)
    {
    var customer = new Customer(Guid.NewGuid(), email.Trim().ToLowerInvariant(), name);
    await repo.AddAsync(customer, ct);
    await repo.SaveChangesAsync(ct);
    }
    }

    Line-by-line code explanation

    • interface ICustomerRepository declares persistence operations without mentioning SQL or EF.
    • Task<Customer?> FindByIdAsync(...) returns a nullable customer — honest about missing records.
    • Task AddAsync(...) and Task SaveChangesAsync(...) separate insert from commit.
    • sealed record Customer(...) is a lightweight domain model passed across layers.
    • CustomerService(ICustomerRepository repo) depends on the abstraction, not a concrete database class.
    • RegisterAsync(string email, string name, ...) orchestrates customer creation at the application layer.
    • email.Trim().ToLowerInvariant() normalizes email before persistence.
    • new Customer(Guid.NewGuid(), ...) creates the entity with a fresh identifier.
    • await repo.AddAsync(customer, ct) stages the insert through the repository abstraction.
    • await repo.SaveChangesAsync(ct) commits the unit of work transactionally.

    Key takeaway: CustomerService knows nothing about SQL — only ICustomerRepository abstraction. EF implementation lives in Infrastructure layer.

    Real-world use

    Where you'll use this in production

    • Repository pattern over EF Core DbSets.
    • Payment gateway abstracting Stripe vs Adyen.
    • Cloud storage abstracting Azure Blob vs S3.
    • Logging abstracted via ILogger interface.

    Best practices

    • Abstractions shaped by client needs, not database tables.
    • Keep interfaces small — Interface Segregation Principle.
    • Place interfaces in domain/application layer.
    • Avoid leaking ORM types through abstractions.
    • Name abstractions by capability not technology.

    Common mistakes

    • IRepository with 30 CRUD methods nobody uses.
    • Returning IQueryable from repository — leaks LINQ provider.
    • Abstract class with only abstract members — use interface.
    • Business logic in repository implementation.

    Advanced interview questions

    Q1BeginnerAbstraction vs encapsulation?
    Abstraction: simplified model; encapsulation: hiding internal state/mechanism.
    Q2BeginnerWhy IRepository?
    Decouple domain from persistence; swap/test implementations.
    Q3Intermediateabstract class when?
    Shared implementation + partial contract for closely related types.
    Q4IntermediateLeaky abstraction example?
    Exposing SqlException or DbContext from repository interface.
    Q5AdvancedDesign abstraction for file storage usable in tests without cloud.
    IFileStorage Store/Get/Delete with stream; LocalFileStorage for tests; AzureBlobStorage for prod; register via DI.

    Summary

    Abstraction simplifies complex systems via focused contracts. Interfaces and abstract classes define what, not how. Layered apps depend on abstractions, not concretions. Repository and gateway patterns are daily abstraction tools. Next: interfaces in depth.

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