EviCache 2.2.0

dotnet add package EviCache --version 2.2.0
                    
NuGet\Install-Package EviCache -Version 2.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EviCache" Version="2.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EviCache" Version="2.2.0" />
                    
Directory.Packages.props
<PackageReference Include="EviCache" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EviCache --version 2.2.0
                    
#r "nuget: EviCache, 2.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EviCache@2.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EviCache&version=2.2.0
                    
Install as a Cake Addin
#tool nuget:?package=EviCache&version=2.2.0
                    
Install as a Cake Tool

About

nuget Codacy Badge Codacy Badge

EviCache is a lightweight, thread-safe, in-memory caching library for .NET.

It supports multiple eviction policies and offers extended cache operations. Moreover, it provides metrics and inspection capabilities.

Table of Contents

Overview

Quick start

using EviCache;
using EviCache.Enums;
using EviCache.Options;

// Create a cache with LRU and capacity 100
var cache = new Cache<string, string>(new CacheOptions(
    capacity: 100,
    evictionPolicy: EvictionPolicy.LRU));

// Put & Get
cache.Put("user:1", "André");
var name = cache.Get("user:1"); // "André"

// GetOrAdd (adds on miss, returns existing on hit)
var color = cache.GetOrAdd("color", "blue");

// Per-item absolute expiration (e.g., 1 minute)
cache.Put("otp", "123456",
    new CacheItemOptions {
        Expiration = new ExpirationOptions.Absolute(TimeSpan.FromMinutes(1))
    });
Async
// Same semantics, but async + cancellation support
await cache.PutAsync("k", "v", ct);
var value = await cache.GetAsync("k", ct);
var (found, v) = await cache.TryGetAsync("missing", ct);

Eviction policies

Choose via CacheOptions.EvictionPolicy:

  • LRU: evicts least-recently-used.
  • LFU: evicts least-frequently-used.
  • FIFO: evicts oldest inserted.
  • NoEviction: refuse to add when full; throws CacheFullException.

When capacity is full, the cache evicts one candidate (if the policy allows). If no candidate can be evicted or policy is NoEviction, a CacheFullException is thrown with diagnostic data (capacity, attempted key, policy).

Expiration (TTL)

Set expiration globally (default for all items) or per item:

  • ExpirationOptions.Absolute(TimeSpan ttl): expires at now + ttl.
  • ExpirationOptions.Sliding(TimeSpan ttl): expires if not accessed within ttl.
  • ExpirationOptions.None: no expiration.
Examples:
// Global default expiration: absolute 10 minutes
var cache = new Cache<string, byte[]>(new CacheOptions(
    100, EvictionPolicy.LFU,
    new ExpirationOptions.Absolute(TimeSpan.FromMinutes(10))));

// Per-item sliding expiration: 5 minutes
cache.Put("session:12", session,
    new CacheItemOptions {
        Expiration = new ExpirationOptions.Sliding(TimeSpan.FromMinutes(5))
    });

Expired items are purged lazily on access and during capacity checks; they won’t appear in GetKeys()/GetSnapshot().

API overview

  • Retrieval
    • Get(key) → value (throws if missing).
    • TryGet(key, out value) / TryGetAsync → no throw.
    • ContainsKey(key) / ContainsKeyAsync → does not affect hit/miss counters.
  • Mutation
    • Put(key, value) / Put(key, value, options) → insert or update.
    • AddOrUpdate(key, value) → inserts on miss; returns the provided value.
    • GetOrAdd(key, value) → returns existing value on hit; otherwise, inserts and returns the provided value.
    • Remove(key) → bool; Clear() → clears all.
  • Inspection
    • GetKeys()ImmutableList<TKey> of non-expired keys (order depends on policy).
    • GetSnapshot()ImmutableList<KeyValuePair<TKey,TValue>> of non-expired entries.
  • Metadata
    • GetMetadata(key) / TryGetMetadata(key, out meta) → last access/update, access count, expiration, etc.
  • Metrics
    • Capacity, Count (purges expired first), Hits, Misses, Evictions.

Hits & Misses

  • Successful Get/TryGet/GetOrAdd (hit path) increments Hits and updates access metadata + policy structures.
  • Miss paths increment Misses.
  • ContainsKey is intentionally “cold”: it checks existence without touching metrics or access ordering.

Thread-safety

All public operations are protected by an internal SemaphoreSlim, ensuring a single writer/reader critical section. Both sync and async APIs are safe to call concurrently.

Disposal semantics

  • If a cached value implements IDisposable/IAsyncDisposable, it is disposed when the entry is removed, evicted, updated (when replacing a different instance), or during Clear().
  • Clear() gathers disposables and disposes them in the background (respecting the provided cancellation token in ClearAsync). Errors during disposal are logged.

Logging

Pass an ILogger to the constructor or rely on the default NullLogger. Notable events:

  • Initialization (capacity, policy) at Information.
  • Evictions at Debug.
  • Errors during eviction selection or background disposal at Error.

Exceptions

  • KeyNotFoundException: Get on a non-existing/expired key.
  • CacheFullException: when full and:
    • policy is NoEviction, or
    • an eviction candidate couldn’t be selected/removed.

CacheFullException includes Capacity, the attempted key (if available), and EvictionPolicy for diagnostics.

Performance notes

  • Keys are tracked per policy for fast candidate selection; GetKeys() returns a filtered, immutable snapshot without expired entries.
  • Count triggers a purge of expired items before returning the size.
  • Avoid calling ContainsKey as a pre-check before Get — do a single TryGet to minimize lock acquisitions.

<a id="feedback"></a>

Feedback & Contributing

EviCache is released as open source under the MIT license. Bug reports and contributions are welcome at the GitHub repository.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  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 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
2.2.0 280 9/19/2025
2.1.0 227 4/21/2025
2.0.1 221 4/8/2025
2.0.0 191 3/16/2025
1.4.1 236 3/3/2025
1.4.0 124 3/1/2025
1.3.1 163 2/28/2025
1.3.0 148 2/24/2025
1.2.0 167 2/22/2025
1.1.0 143 2/19/2025
1.0.0 182 2/17/2025