Memoization.Net
1.1.1
dotnet add package Memoization.Net --version 1.1.1
NuGet\Install-Package Memoization.Net -Version 1.1.1
<PackageReference Include="Memoization.Net" Version="1.1.1" />
<PackageVersion Include="Memoization.Net" Version="1.1.1" />
<PackageReference Include="Memoization.Net" />
paket add Memoization.Net --version 1.1.1
#r "nuget: Memoization.Net, 1.1.1"
#:package Memoization.Net@1.1.1
#addin nuget:?package=Memoization.Net&version=1.1.1
#tool nuget:?package=Memoization.Net&version=1.1.1
Memoization.Net
A high-performance memoization library for .NET that provides automatic function result caching to improve performance by avoiding redundant computations.
Overview
Memoization is an optimization technique that stores the results of expensive function calls and returns the cached result when the same inputs occur again. This library provides a simple and efficient way to memoize functions in C# using Microsoft's IMemoryCache
.
Features
- High Performance: Built on top of
Microsoft.Extensions.Caching.Abstractions
for optimal performance - Generic Support: Supports functions with up to 16 parameters
- Flexible Caching: Use global default cache or specify per-function cache instances
- Cache Options: Full support for
MemoryCacheEntryOptions
(TTL, size limits, etc.) - Exception Safety: Failed computations don't pollute the cache
- Thread Safe: Operations are thread-safe when using thread-safe
IMemoryCache
implementations - Multi-Target: Supports .NET Standard 2.0/2.1, .NET Framework 4.6.2, .NET 8.0, and .NET 9.0
Installation
dotnet add package Memoization.Net
Quick Start
1. Initialize Default Cache
using Microsoft.Extensions.Caching.Memory;
using Memoization;
// Set up the default cache (typically done once at application startup)
Memoization.DefaultCache = new MemoryCache(new MemoryCacheOptions
{
SizeLimit = 1000,
CompactionPercentage = 0.25
});
2. Create Memoized Functions
// Example: Expensive recursive function
static int Fibonacci(int n)
{
Console.WriteLine($"Computing Fibonacci({n})");
return n < 2 ? 1 : Fibonacci(n - 1) + Fibonacci(n - 2);
}
// Create memoized version
var memoizedFib = Memoization.Create<int, int>(Fibonacci);
// First call - computes and caches result
var result1 = memoizedFib(10); // Prints computation messages
// Second call - returns cached result instantly
var result2 = memoizedFib(10); // No computation, returns cached result
Advanced Usage
Custom Cache Instance
// Use a specific cache instance
var customCache = new MemoryCache(new MemoryCacheOptions());
var memoizedFunc = Memoization.Create(expensiveFunction, customCache);
Cache Options
// Configure cache entry options
var options = new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
SlidingExpiration = TimeSpan.FromMinutes(5),
Priority = CacheItemPriority.High
};
var memoizedFunc = Memoization.Create(expensiveFunction, options);
Multi-Parameter Functions
// Function with multiple parameters
static double ExpensiveCalculation(double x, double y, int iterations)
{
// Simulate expensive computation
return Math.Pow(x + y, iterations % 10);
}
var memoized = Memoization.Create<double, double, int, double>(ExpensiveCalculation);
var result = memoized(3.14, 2.71, 1000);
Performance Considerations
Cache Key Generation
The library uses tuples of input parameters as cache keys. For best performance:
- Ensure parameter types implement efficient
GetHashCode()
andEquals()
methods - Avoid using mutable objects as parameters
- Consider the memory overhead of storing keys and values
Memory Management
// Configure cache with size limits to prevent memory issues
var options = new MemoryCacheOptions
{
SizeLimit = 1000,
CompactionPercentage = 0.20
};
var cache = new MemoryCache(options);
Exception Handling
Failed function calls do not pollute the cache:
var memoized = Memoization.Create<int, string>(x =>
{
if (x < 0) throw new ArgumentException("Negative input");
return x.ToString();
});
try { memoized(-1); } catch { /* Exception thrown, nothing cached */ }
var result = memoized(5); // Will compute and cache successfully
Thread Safety
All memoization operations depend on the thread safety of the underlying IMemoryCache
implementation. Since this library uses Microsoft.Extensions.Caching.Abstractions
, the thread safety depends on the specific IMemoryCache
implementation being used. The default Microsoft.Extensions.Caching.Memory
implementation is thread-safe, so multiple threads can safely call memoized functions concurrently:
var memoized = Memoization.Create(expensiveFunction);
// Safe to call from multiple threads (with thread-safe IMemoryCache implementation)
Parallel.For(0, 100, i =>
{
var result = memoized(i % 10); // Concurrent access is safe
});
Note: While cache operations are typically thread-safe, the memoized function itself should be thread-safe (or pure) to avoid issues with concurrent execution. Additionally, when the same inputs are being processed concurrently by multiple threads, the expensive function may be executed multiple times before the result is cached.
Best Practices
- Initialize Once: Set up
DefaultCache
once during application startup - Pure Functions: Only memoize pure functions (same input always produces same output)
- Immutable Parameters: Use immutable types as function parameters when possible
- Cache Sizing: Configure appropriate cache size limits to prevent memory leaks
- Monitoring: Monitor cache hit ratios and memory usage in production
Examples
Database Query Caching
// Cache expensive database queries
var cachedQuery = Memoization.Create<int, User>(userId =>
{
return database.Users.FirstOrDefault(u => u.Id == userId);
}, new MemoryCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
});
Computational Results
// Cache complex mathematical computations
var cachedCompute = Memoization.Create<double[], double>(weights =>
{
return weights.Select((w, i) => w * Math.Pow(i, 2)).Sum();
});
License
This project is licensed under the GNU General Public License v3.0 - see the LICENSE for details.
Related Projects
- Microsoft.Extensions.Caching.Memory - The underlying caching implementation
- Memoization (Wikipedia) - Background on the memoization technique
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 was computed. net462 is compatible. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.6.2
- Microsoft.Extensions.Caching.Abstractions (>= 2.1.0)
- System.ValueTuple (>= 4.4.0)
-
.NETStandard 2.0
- Microsoft.Extensions.Caching.Abstractions (>= 2.1.0)
-
.NETStandard 2.1
- Microsoft.Extensions.Caching.Abstractions (>= 2.1.0)
-
net8.0
- Microsoft.Extensions.Caching.Abstractions (>= 2.1.0)
-
net9.0
- Microsoft.Extensions.Caching.Abstractions (>= 2.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
1.1.1 | 114 | 7/15/2025 |
1.1.0-beta.1.gb6ba33d | 181 | 8/17/2022 |
1.0.0 | 1,510 | 1/3/2018 |
# Release Notes
## Version 1.1.1
- **Breaking**: Multi-framework targeting - now supports .NET Standard 2.0/2.1, .NET Framework 4.6.2, .NET 8.0, and .NET 9.0
- **Feature**: Added nullable reference types support for modern .NET versions
- **Improvement**: Enhanced package metadata with better description and tags
- **Improvement**: Added comprehensive documentation generation
- **Improvement**: Improved NuGet package configuration following modern best practices
## Version 1.1.0-beta.1 (August 17, 2022)
- **Feature**: Migrated project to OneDotNet monorepo structure
- **Improvement**: Updated build configuration and dependency management
- **Improvement**: Enhanced package versioning with Nerdbank.GitVersioning
- **Fix**: Updated dependencies and resolved compatibility issues
## Version 1.0.0 (Initial Release)
- **Feature**: Initial release with core memoization functionality
- **Feature**: Support for Microsoft.Extensions.Caching.Abstractions integration
- **Feature**: Text template-based code generation for multiple function signatures
- **Feature**: High-performance function result caching
- **Feature**: Efficient memory management for cached results
- **Target**: .NET Standard 2.0 support for broad compatibility