Template-Method-Pattern :👈 👉:Terms_Of_Use

CRTP (Curiously Recurring Template Pattern) in C#

🧩 CRTP (Curiously Recurring Template Pattern) in C#

The Curiously Recurring Template Pattern (CRTP) is a design technique where a class uses itself as a parameter to a generic base class. It’s more common in C++, but C# supports a similar approach using generics with constraints.

🔑 Core Idea

A base class defines behavior that depends on the derived class type.
This allows:

  • Compile-time polymorphism (instead of runtime via virtual methods).
  • Strongly typed self-references in generic hierarchies.

📖 Example in C#

using System;

// Base class using CRTP
public abstract class BaseViewModel<T> where T : BaseViewModel<T>
{
    public void Initialize()
    {
        Console.WriteLine($"{typeof(T).Name} initializing...");
        ((T)this).OnInitialize(); // Call derived implementation
    }

    // Derived class must implement
    protected abstract void OnInitialize();
}

// Derived ViewModel
public class UserViewModel : BaseViewModel<UserViewModel>
{
    protected override void OnInitialize()
    {
        Console.WriteLine("UserViewModel: Loading user data...");
    }
}

public class ProductViewModel : BaseViewModel<ProductViewModel>
{
    protected override void OnInitialize()
    {
        Console.WriteLine("ProductViewModel: Loading product catalog...");
    }
}

class Program
{
    static void Main()
    {
        var userVM = new UserViewModel();
        userVM.Initialize();

        var productVM = new ProductViewModel();
        productVM.Initialize();
    }
}

📝 Output

UserViewModel initializing...
UserViewModel: Loading user data...
ProductViewModel initializing...
ProductViewModel: Loading product catalog...

✅ Pros

  • Compile-time safety: Derived type is enforced by the generic constraint.
  • Avoids virtual calls: Can reduce runtime overhead compared to polymorphism.
  • Cleaner APIs: Base class can expose methods that return the derived type (fluent APIs).
  • Consistency: Ensures derived classes follow a strict pattern.

⚠️ Cons

  • Complexity: Can be confusing for developers unfamiliar with CRTP.
  • Less flexible than runtime polymorphism: Works best when hierarchy is known at compile time.
  • Limited in C# compared to C++: No template specialization, so patterns are less powerful.
  • Harder debugging: Generic type recursion can make stack traces harder to read.

🏆 Best Practices

  • Use CRTP when you want compile-time polymorphism and fluent APIs.
  • Keep hierarchies shallow to avoid complexity.
  • Document clearly why CRTP is used (many devs expect runtime polymorphism).
  • Prefer CRTP for framework/lifecycle base classes (like ViewModels, Builders, Fluent APIs).

🚫 What to Avoid

  • Don’t use CRTP just to “look clever” — it adds cognitive load.
  • Avoid deep inheritance chains with CRTP (hard to maintain).
  • Don’t mix CRTP with heavy runtime polymorphism — it defeats the purpose.
  • Avoid exposing CRTP-based APIs to external consumers unless absolutely necessary (they may find it confusing).

⚡ Real-World Use Case

In MVVM frameworks (like .NET MAUI or WPF), CRTP can be used for a BaseViewModel lifecycle:

  • BaseViewModel<T> defines lifecycle hooks (Initialize, OnDestroy).
  • Each derived ViewModel (e.g., UserViewModel, ProductViewModel) enforces type safety and lifecycle consistency.
Back to Index
Template-Method-Pattern :👈 👉:Terms_Of_Use
*