Created
October 3, 2025 10:19
-
-
Save musoftware/39ec4e1e588a0584b2e8a345644ef660 to your computer and use it in GitHub Desktop.
Generic TTL Cache in C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Threading; | |
| using System.Threading.Tasks; | |
| public class Program | |
| { | |
| public static async Task Main(string[] args) | |
| { | |
| // Create a cache with a 5-second Time-To-Live. | |
| var weatherCache = new TTLCache(TimeSpan.FromSeconds(5)); | |
| string city = "Suez"; | |
| // 1. First call is a CACHE MISS and executes the slow method. | |
| string result1 = weatherCache.Execute( | |
| key: $"weather:{city}", | |
| function: () => FetchWeatherData(city) | |
| ); | |
| Console.WriteLine(result1); | |
| Console.WriteLine("\nImmediately calling again..."); | |
| // 2. Second call is a CACHE HIT and returns instantly. | |
| string result2 = weatherCache.Execute( | |
| key: $"weather:{city}", | |
| function: () => FetchWeatherData(city) | |
| ); | |
| Console.WriteLine(result2); | |
| // 3. Wait for the cache item to expire. | |
| Console.WriteLine("\nWaiting 6 seconds for cache to expire..."); | |
| await Task.Delay(6000); | |
| // 4. Third call is a CACHE MISS again. | |
| string result3 = weatherCache.Execute( | |
| key: $"weather:{city}", | |
| function: () => FetchWeatherData(city) | |
| ); | |
| Console.WriteLine(result3); | |
| } | |
| /// <summary> | |
| /// Simulates a slow network call to an API. | |
| /// </summary> | |
| public static string FetchWeatherData(string city) | |
| { | |
| Console.WriteLine($"--- Making a slow API call for {city}... ---"); | |
| Thread.Sleep(2000); // Simulate 2 seconds of network latency | |
| return $"Weather for {city} as of {DateTime.Now:T}: 28°C, Clear Skies"; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Concurrent; | |
| using System.Threading.Tasks; | |
| public class TTLCache | |
| { | |
| private class CacheItem | |
| { | |
| public object Value { get; } | |
| public DateTime ExpirationTime { get; } | |
| public CacheItem(object value, TimeSpan ttl) | |
| { | |
| Value = value; | |
| ExpirationTime = DateTime.UtcNow.Add(ttl); | |
| } | |
| public bool IsExpired => DateTime.UtcNow >= ExpirationTime; | |
| } | |
| private readonly ConcurrentDictionary<string, CacheItem> _cache = new(); | |
| private readonly TimeSpan _ttl; | |
| public TTLCache(TimeSpan ttl) | |
| { | |
| _ttl = ttl; | |
| } | |
| /// <summary> | |
| /// Executes the function, using a cached result if a valid one exists for the given key. | |
| /// </summary> | |
| /// <typeparam name="T">The return type of the function.</typeparam> | |
| /// <param name="key">A unique key to identify this function call.</param> | |
| /// <param name="function">The function to execute if no valid cached item is found.</param> | |
| /// <returns>The result of the function, either from cache or a fresh execution.</returns> | |
| public T Execute<T>(string key, Func<T> function) | |
| { | |
| if (_cache.TryGetValue(key, out var item) && !item.IsExpired) | |
| { | |
| Console.WriteLine($"CACHE HIT for key: '{key}'."); | |
| return (T)item.Value; | |
| } | |
| Console.WriteLine($"CACHE MISS or EXPIRED for key: '{key}'. Executing function."); | |
| T result = function(); | |
| _cache[key] = new CacheItem(result, _ttl); | |
| return result; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment