RentADeveloper.AutoIndexCache 1.3.0

dotnet add package RentADeveloper.AutoIndexCache --version 1.3.0
                    
NuGet\Install-Package RentADeveloper.AutoIndexCache -Version 1.3.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="RentADeveloper.AutoIndexCache" Version="1.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RentADeveloper.AutoIndexCache" Version="1.3.0" />
                    
Directory.Packages.props
<PackageReference Include="RentADeveloper.AutoIndexCache" />
                    
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 RentADeveloper.AutoIndexCache --version 1.3.0
                    
#r "nuget: RentADeveloper.AutoIndexCache, 1.3.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 RentADeveloper.AutoIndexCache@1.3.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=RentADeveloper.AutoIndexCache&version=1.3.0
                    
Install as a Cake Addin
#tool nuget:?package=RentADeveloper.AutoIndexCache&version=1.3.0
                    
Install as a Cake Tool

license semver

AutoIndexCache

A high-performance, thread-safe cache for .NET applications that provides automatic indexing of cached data.

using System;
using RentADeveloper.AutoIndexCache;

public class User
{
    public Int64 GroupId { get; set; }
    public Int64 Id { get; set; }
    public Boolean IsActive { get; set; }
    public String UserName { get; set; }
}

public class Program
{
    public static void Main(String[] args)
    {
        var cache = new AutoIndexCache();

        cache.SetItemsLoader(() => LoadUsers());

        // Get all users:
        cache.Items<User>().GetAllItems();

        // Get the user that has the Id 1:
        cache.Items<User>().UniqueIndex(a => a.Id).GetItemOrDefault(1);

        // Get all users that belong to group 1:
        cache.Items<User>().NonUniqueIndex(a => a.GroupId).GetItems(1);

        // Get all active users of group 10:
        cache.Items<User>().NonUniqueIndex(a => (a.IsActive, a.GroupId)).GetItems((true, 10));

        // Get all Ids of users:
        cache.Items<User>().UniqueIndex(a => a.Id).GetKeys();

        // Reset the users cache (LoadUsers will be called again next time User items are requested from the cache):
        cache.Items<User>().Reset();
    }

    private static User[] LoadUsers()
    {
        var result = new User[10_000];

        for (var i = 1; i <= result.Length; i++)
        {
            result[i - 1] = new() { Id = i, UserName = "User " + i, GroupId = i % 2 == 0 ? 2 : 1, IsActive = i % 2 == 0 };
        }

        return result;
    }
}

Performance

AutoIndexCache is blazingly fast (as a cache should be).
However, some overhead is still needed to make it thread-safe and for the auto indexing, so a hand crafted custom solution might be even faster.

Benchmarks

In the following benchmarks AutoIndexCache is compared to the Dictionary<TKey,TValue> type.
You can find the source code of the bechmarks here.

<img width="3054" height="1276" alt="image" src="https://github.com/user-attachments/assets/55da6363-5ea1-4445-8c5a-5db3b3bc6c39" />

Explanation

..._Dicationary

In these benchmarks the Dictionary<TKey,TValue> is used to index cached items.
There is hardly any faster soltuion in .NET to index cached items.
However, the Dictionary is completely non-thread-safe.

..._AutoIndexCache

In these benchmarks the AutoIndexCache is used.

..._AutoIndexCacheOptimized

In these bechmarks, also, the AutoIndexCache is used.
However, a trick was applied to drastically improve the performance:

To access cached items you need to call the AutoIndexCache.Items<TItem> method.
And to access indexes you need to call the ItemsList<TItem>.NonUniqueIndex<TKey> and ItemsList<TItem>.UniqueIndex<TKey> methods.
These methods have some overhead, because they need to be thread-safe.

Instead of calling these method each time you want to access cached items or indexes, you can just call them once and store their return values in fields (so in essence, you are caching the cache 😃).
This way the performance of the cache is improved drastically.

So instead of this:

class Service
{
    public Service(IAutoIndexCache cache)
    {
        this.cache = cache;
    }

    public User? GetUserById(Int64 id)
    {
        return this.cache.Items<User>().UniqueIndex(a => a.Id).GetItemOrDefault(id);
    }

    private readonly IAutoIndexCache cache;
}

you do this:

class Service
{
    public Service(IAutoIndexCache cache)
    {
        this.cache = cache;
        this.users = this.cache.Items<User>();
        this.userById = this.users.UniqueIndex(a => a.Id);
    }

    public User? GetUserById(Int64 id)
    {
        return this.userById.GetItemOrDefault(id);
    }

    private readonly IAutoIndexCache cache;
    private readonly IUniqueIndex<User, Int64> userById;
    private readonly IItemsList<User> users;
}

License

This library is licensed under the MIT license.

Installation

First, install NuGet.

Then download a release from the releases page and install via the NuGet Package Manager:

PM> Install-Package AutoIndexCache -Source PathToTheNuGetPackage

Documentation

The API documentation can be found here.

Contributors

Main contributors

  • David Liebeherr (info@rent-a-developer.de)
Product 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 was computed.  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. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.

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.3.0 662 12/2/2025

Performance optimizations.