In this lesson, you’ll learn how to choose between generic type parameters and enums to design systems that balance performance with flexibility.
When you need to handle multiple types in your code, you face a fundamental choice: Generic types (Generics) or Enums. While both allow your code to work with different data, they operate in opposite ways.
The Power of Generics (Static Abstraction)
Generics use a process called monomorphization. When you define a function like fn process<T: Processor>(item: T), the Rust compiler generates a specialized version of that function for every concrete type you pass in.
- When to use: Use generics when you know all possible types at compile-time and you want maximum performance. Because the compiler knows the exact type, it can "inline" the logic, eliminating the overhead of checking which type is being used. It is purely static abstraction.
The Power of Enums (Runtime Branching)
Enums, conversely, represent a fixed set of choices known at design time, but they handle those choices through runtime branching.
- When to use: Use enums when you have a closed set of variants and you need to store them in a single collection (like a
Vec<MyEnum>) or when your logic requires deciding which path to take while the program is actually running.
Choosing Your Strategy
Imagine you are building a rendering engine. If you are processing a specific sequence of operations where speed is critical, use a Generic to lock in the type and allow the compiler to optimize the math. If you are building a user interface where a list might contain a Button, a Slider, or a TextField, use an Enum.
// Generic: High performance, fixed at compile-time
fn calculate<T: Shape>(s: T) { s.area(); }
// Enum: Flexible, allows lists of different types
enum Widget {
Button,
Slider,
TextField,
}
The difference comes down to the cost of "looking up" the type. Generics resolve the type at compile-time, while enums require the CPU to inspect the variant at runtime to decide what code to execute. Choose generics for performance-critical hotspots, and enums for collections that need to store multiple, related types.
Key Takeaway: Use generics for compile-time optimization where the type is fixed per call, and use enums for runtime flexibility when you need to switch between different behaviors on the fly.