The Problem: The "LINQ Tax"
In Part 1, we successfully replaced magic numbers with Records. To find a specific status, we used LINQ:
var status = Status.All.SingleOrDefault(x => x.Id == productStatusId);
While this works perfectly, it has two drawbacks:
- Complexity: You have to repeat this LINQ logic every time you need to fetch a status.
- Performance: LINQ performs a linear search O(n). For a large set of statuses in a high-traffic app, this is unnecessary overhead.
The Solution: The Internal Lookup
We can optimize this by adding a private Dictionaryinside our Status class. This gives us instant O(1) lookups regardless of how many statuses you have.
public record StatusValue(int Id, string Description);
public static class Status
{
public static readonly StatusValue Pending = new(1, "Pending Approval");
public static readonly StatusValue Available = new(2, "Available for Sale");
public static readonly StatusValue OutOfStock = new(3, "Out of Stock");
public static readonly StatusValue[] All = { Pending, Available, OutOfStock };
private static readonly Dictionary<int, StatusValue> _lookup = All.ToDictionary(s => s.Id);
// O(1) access to the full object
public static StatusValue? Get(int id) => _lookup.GetValueOrDefault(id);
// Quick existence check
public static bool Exists(int id) => _lookup.ContainsKey(id);
// Accessing properties
public static string GetDescription(int id) => Get(id)?.Description ?? "Unknown";
}
How your Business Logic looks now
Instead of writing LINQ queries, your services now look like this:
if (Status.Exists(userInputId))
{
var label = Status.GetDescription(userInputId);
Console.WriteLine($"Processing: {label}");
}
Try it yourself
Further Reading
- Dictionary Class — Documentation for our $O(1)$ lookup engine.
Version Note: These performance optimizations are designed for .NET 6+ environments.
Top comments (0)