KGy SOFT

CacheTKey, TValue Class

KGy SOFT Core Libraries Help
Represents a generic cache. If an item loader is specified, then cache expansion is transparent: the user needs only to read the indexer to retrieve items. When a non-existing key is accessed, then the item is loaded automatically by the loader function that was passed to the constructor. If the cache is full (elements Count reaches the Capacity) and a new element has to be stored, then the oldest or least recent used element (depends on the value of Behavior) is removed from the cache.
See the Remarks section for details and an example.
Inheritance Hierarchy

SystemObject
  KGySoft.CollectionsCacheTKey, TValue

Namespace:  KGySoft.Collections
Assembly:  KGySoft.CoreLibraries (in KGySoft.CoreLibraries.dll) Version: 5.0.0-rc.1
Syntax

[SerializableAttribute]
public class Cache<TKey, TValue> : IDictionary<TKey, TValue>, 
	ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, 
	IEnumerable, ICache, IDictionary, ICollection, ISerializable, 
	IDeserializationCallback, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>

Type Parameters

TKey
Type of the keys stored in the cache.
TValue
Type of the values stored in the cache.

The CacheTKey, TValue type exposes the following members.

Constructors

  NameDescription
Public methodCacheTKey, TValue
Initializes a new instance of the CacheTKey, TValue class with default capacity of 128 and no item loader.
Public methodCacheTKey, TValue(IEqualityComparerTKey)
Initializes a new instance of the CacheTKey, TValue class with the specified comparer, default capacity of 128 and no item loader.
Public methodCacheTKey, TValue(FuncTKey, TValue, IEqualityComparerTKey)
Creates a new CacheTKey, TValue instance with the given itemLoader and comparer using default capacity of 128.
Public methodCacheTKey, TValue(Int32, IEqualityComparerTKey)
Initializes a new instance of the CacheTKey, TValue class with specified capacity capacity and comparer and no item loader.
Protected methodCacheTKey, TValue(SerializationInfo, StreamingContext)
Initializes a new instance of the CacheTKey, TValue class from serialized data.
Public methodCacheTKey, TValue(FuncTKey, TValue, Int32, IEqualityComparerTKey)
Creates a new CacheTKey, TValue instance with the given itemLoader, capacity and comparer.
Top
Properties

  NameDescription
Public propertyBehavior
Gets or sets the cache behavior when cache is full and an element has to be removed. The cache is full, when Count reaches the Capacity. Default value: RemoveLeastRecentUsedElement.
Public propertyCapacity
Gets or sets the capacity of the cache. If new value is smaller than elements count (value of the Count property), then old or least used elements (depending on Behavior) will be removed from CacheTKey, TValue.
Default value: 128, if the CacheTKey, TValue was initialized without specifying a capacity; otherwise, as it was initialized.
Public propertyCount
Gets number of elements currently stored in this CacheTKey, TValue instance.
Public propertyDisposeDroppedValues
Gets or sets whether internally dropped values are disposed if they implement IDisposable.
Default value: .
Public propertyEnsureCapacity
Gets or sets whether adding the first item to the cache or resetting Capacity on a non-empty cache should allocate memory for all cache entries.
Default value: .
Public propertyItem
Gets or sets the value associated with the specified key. When an element with a non-existing key is read, and an item loader was specified by the appropriate constructor, then the value is retrieved by the specified loader delegate of this CacheTKey, TValue instance.
Public propertyKeys
Gets the keys stored in the cache in evaluation order.
Public propertyValues
Gets the values stored in the cache in evaluation order.
Top
Methods

  NameDescription
Public methodAdd
Adds an element with the provided key and value to the CacheTKey, TValue.
Public methodClear
Removes all keys and values from the CacheTKey, TValue.
Public methodContainsKey
Determines whether the CacheTKey, TValue contains a specific key.
Public methodContainsValue
Determines whether the CacheTKey, TValue contains a specific value.
Public methodEquals
Determines whether the specified object is equal to the current object.
(Inherited from Object.)
Protected methodFinalize
Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection.
(Inherited from Object.)
Public methodGetEnumerator
Returns an enumerator that iterates through the CacheTKey, TValue elements in the evaluation order.
Public methodGetHashCode
Serves as the default hash function.
(Inherited from Object.)
Protected methodGetObjectData
In a derived class populates a SerializationInfo with the additional data of the derived type needed to serialize the target object.
Public methodGetStatistics
Gets an ICacheStatistics instance that provides statistical information about this CacheTKey, TValue.
Public methodGetThreadSafeAccessor
Gets a thread safe accessor for this CacheTKey, TValue instance. As it provides only a single readable indexer, it makes sense only if an item loader was passed to the appropriate constructor and the cache will not be accessed by other members but via the returned accessor.
Public methodGetValueUncached
Loads the value of the key even if it already exists in the CacheTKey, TValue by using the item loader that was passed to the constructor.
Public methodGetType
Gets the Type of the current instance.
(Inherited from Object.)
Protected methodMemberwiseClone
Creates a shallow copy of the current Object.
(Inherited from Object.)
Protected methodOnDeserialization
In a derived class restores the state the deserialized instance.
Public methodRefreshValue
Refreshes the value of the key in the CacheTKey, TValue even if it already exists in the cache by using the item loader that was passed to the constructor.
Public methodRemove
Removes the value with the specified key from the CacheTKey, TValue.
Public methodReset
Clears the CacheTKey, TValue and resets statistics.
Public methodToString
Returns a string that represents the current object.
(Inherited from Object.)
Public methodTouch
Renews the value with the specified key in the evaluation order.
Public methodTryGetValue
Tries to gets the value associated with the specified key without using the item loader passed to the constructor.
Top
Extension Methods

  NameDescription
Public Extension MethodAddRangeKeyValuePairTKey, TValue (Defined by CollectionExtensions.)
Public Extension MethodAsThreadSafeKeyValuePairTKey, TValue (Defined by CollectionExtensions.)
Public Extension MethodConvert(Type, CultureInfo)Overloaded.
Converts an Object specified in the obj parameter to the desired targetType.
See the Examples section of the generic ConvertTTarget(Object, CultureInfo) overload for an example.
(Defined by ObjectExtensions.)
Public Extension MethodCode exampleConvertTTarget(CultureInfo)Overloaded.
Converts an Object specified in the obj parameter to the desired TTarget.
(Defined by ObjectExtensions.)
Public Extension MethodForEachKeyValuePairTKey, TValue
Similarly to the List<T>.ForEach method, processes an action on each element of an enumerable collection.
(Defined by EnumerableExtensions.)
Public Extension MethodGetRandomElementKeyValuePairTKey, TValue(Boolean)Overloaded.
Gets a random element from the enumerable source using a new Random instance.
(Defined by EnumerableExtensions.)
Public Extension MethodGetRandomElementKeyValuePairTKey, TValue(Random, Boolean)Overloaded.
Gets a random element from the enumerable source using a specified Random instance.
(Defined by EnumerableExtensions.)
Public Extension MethodIn (Defined by ObjectExtensions.)
Public Extension MethodIndexOf(FuncObject, Boolean)Overloaded.
Searches for an element in the source enumeration where the specified predicate returns .
(Defined by EnumerableExtensions.)
Public Extension MethodIndexOf(Object)Overloaded.
Searches for an element in the source enumeration.
(Defined by EnumerableExtensions.)
Public Extension MethodIndexOfKeyValuePairTKey, TValue(FuncKeyValuePairTKey, TValue, Boolean)Overloaded.
Searches for an element in the source enumeration where the specified predicate returns .
(Defined by EnumerableExtensions.)
Public Extension MethodIndexOfKeyValuePairTKey, TValue(KeyValuePairTKey, TValue)Overloaded.
Searches for an element in the source enumeration.
(Defined by EnumerableExtensions.)
Public Extension MethodIsNullOrEmptyOverloaded.
Determines whether the specified source is  or empty (has no elements).
(Defined by EnumerableExtensions.)
Public Extension MethodIsNullOrEmptyKeyValuePairTKey, TValueOverloaded.
Determines whether the specified source is  or empty (has no elements).
(Defined by EnumerableExtensions.)
Public Extension MethodShuffleKeyValuePairTKey, TValueOverloaded.
Shuffles an enumerable source (randomizes its elements) using a new Random instance.
(Defined by EnumerableExtensions.)
Public Extension MethodShuffleKeyValuePairTKey, TValue(Int32)Overloaded.
Shuffles an enumerable source (randomizes its elements) using the provided seed with a new Random instance.
(Defined by EnumerableExtensions.)
Public Extension MethodShuffleKeyValuePairTKey, TValue(Random)Overloaded.
Shuffles an enumerable source (randomizes its elements) using a specified Random instance.
(Defined by EnumerableExtensions.)
Public Extension MethodToCircularListKeyValuePairTKey, TValue (Defined by EnumerableExtensions.)
Public Extension MethodTryAdd(Object, Boolean, Boolean)Overloaded.
Tries to add the specified item to the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryAddKeyValuePairTKey, TValue(KeyValuePairTKey, TValue, Boolean, Boolean)Overloaded.
Tries to add the specified item to the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryAddRange(IEnumerable, Boolean, Boolean)Overloaded.
Tries to add the specified collection to the target collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryAddRangeKeyValuePairTKey, TValue(IEnumerableKeyValuePairTKey, TValue, Boolean, Boolean)Overloaded.
Tries to add the specified collection to the target collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryClear(Boolean, Boolean)Overloaded.
Tries to remove all elements from the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryClearKeyValuePairTKey, TValue(Boolean, Boolean)Overloaded.
Tries to remove all elements from the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryConvert(Type, Object)Overloaded.
Tries to convert an Object specified in the obj parameter to the desired targetType.
(Defined by ObjectExtensions.)
Public Extension MethodTryConvert(Type, CultureInfo, Object)Overloaded.
Tries to convert an Object specified in the obj parameter to the desired targetType.
(Defined by ObjectExtensions.)
Public Extension MethodTryConvertTTarget(TTarget)Overloaded.
Tries to convert an Object specified in the obj parameter to the desired TTarget.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example.
(Defined by ObjectExtensions.)
Public Extension MethodTryConvertTTarget(CultureInfo, TTarget)Overloaded.
Tries to convert an Object specified in the obj parameter to the desired TTarget.
See the Examples section of the ConvertTTarget(Object, CultureInfo) method for a related example.
(Defined by ObjectExtensions.)
Public Extension MethodTryGetElementAt(Int32, Object, Boolean, Boolean)Overloaded.
Tries to get an item at the specified index in the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryGetElementAtKeyValuePairTKey, TValue(Int32, KeyValuePairTKey, TValue, Boolean, Boolean)Overloaded.
Tries to get an item at the specified index in the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryInsert(Int32, Object, Boolean, Boolean)Overloaded.
Tries to insert the specified item at the specified index to the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryInsertKeyValuePairTKey, TValue(Int32, KeyValuePairTKey, TValue, Boolean, Boolean)Overloaded.
Tries to insert the specified item at the specified index to the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryInsertRange(Int32, IEnumerable, Boolean, Boolean)Overloaded.
Tries to insert the specified collection into the target collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryInsertRangeKeyValuePairTKey, TValue(Int32, IEnumerableKeyValuePairTKey, TValue, Boolean, Boolean)Overloaded.
Tries to insert the specified collection into the target collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryRemove(Object, Boolean, Boolean)Overloaded.
Tries to remove the specified item from to the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryRemoveKeyValuePairTKey, TValue(KeyValuePairTKey, TValue, Boolean, Boolean)Overloaded.
Tries to remove the specified item from to the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryRemoveAt(Int32, Boolean, Boolean)Overloaded.
Tries to remove an item at the specified index from the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryRemoveAtKeyValuePairTKey, TValue(Int32, Boolean, Boolean)Overloaded.
Tries to remove an item at the specified index from the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTryRemoveRange(Int32, Int32, Boolean, Boolean)Overloaded.
Tries to remove count amount of items from the specified collection at the specified index.
(Defined by EnumerableExtensions.)
Public Extension MethodTryRemoveRangeKeyValuePairTKey, TValue(Int32, Int32, Boolean, Boolean)Overloaded.
Tries to remove count amount of items from the specified collection at the specified index.
(Defined by EnumerableExtensions.)
Public Extension MethodTryReplaceRange(Int32, Int32, IEnumerable, Boolean, Boolean)Overloaded.
Tries to remove count amount of items from the target at the specified index, and to insert the specified collection at the same position. The number of elements in collection can be different from the amount of removed items.
(Defined by EnumerableExtensions.)
Public Extension MethodTryReplaceRangeKeyValuePairTKey, TValue(Int32, Int32, IEnumerableKeyValuePairTKey, TValue, Boolean, Boolean)Overloaded.
Tries to remove count amount of items from the target at the specified index, and to insert the specified collection at the same position. The number of elements in collection can be different from the amount of removed items.
(Defined by EnumerableExtensions.)
Public Extension MethodTrySetElementAt(Int32, Object, Boolean, Boolean)Overloaded.
Tries to set the specified item at the specified index in the collection.
(Defined by EnumerableExtensions.)
Public Extension MethodTrySetElementAtKeyValuePairTKey, TValue(Int32, KeyValuePairTKey, TValue, Boolean, Boolean)Overloaded.
Tries to set the specified item at the specified index in the collection.
(Defined by EnumerableExtensions.)
Top
Remarks

CacheTKey, TValue type provides a fast-access storage with limited capacity and transparent access. If you need to store items that are expensive to retrieve (for example from a database or remote service) and you don't want to run out of memory because of just storing newer and newer elements without getting rid of old ones, then this type might fit your expectations. Once a value is stored in the cache, its retrieval by using its key is very fast, close to O(1).

A cache store must meet the following three criteria:

  1. Associative access - Accessing elements works the same way as in case of the DictionaryTKey, TValue type. CacheTKey, TValue implements both the generic IDictionaryTKey, TValue and the non-generic IDictionary interfaces so can be used similarly as DictionaryTKey, TValue or Hashtable types.
  2. Transparency - Users of the cache need only to read the cache by its indexer property. If needed, elements will be automatically loaded on the first access.
  3. Size management - CacheTKey, TValue type has a Capacity, which is the allowed maximal elements count. If the cache is full, the oldest or least recent used element will be automatically removed from the cache (see Behavior property).

Since CacheTKey, TValue implements IDictionaryTKey, TValue interface, Add, Remove, ContainsKey and TryGetValue methods are available for it, and these methods work exactly the same way as in case the DictionaryTKey, TValue type. But using these methods usually are not necessary, unless we want to manually manage cache content or when cache is initialized without an item loader. Normally after cache is instantiated, it is needed to be accessed only by the getter accessor of its indexer.

Caution note Caution
Serializing a cache instance by IFormatter implementations involves the serialization of the item loader delegate. To deserialize a cache the assembly of the loader must be accessible. If you need to serialize cache instances try to use static methods as data loaders and avoid using anonymous delegates or lambda expressions, otherwise it is not guaranteed that another implementations or versions of CLR will able to deserialize data and resolve the compiler-generated members.
Caution note Caution
.NET Core does not support serializing delegates. If the CacheTKey, TValue instance was initialized by a loader delegate it is possible that serialization throws a SerializationException on some platforms.
Examples

The following example shows the suggested usage of CacheTKey, TValue.
Tip Tip
Try also online.
C#
using System;
using System.Collections.Generic;
using KGySoft.Collections;

class Example
{
    private static Cache<int, bool> isPrimeCache;

    public static void Main()
    {
        // Cache capacity is initialized to store maximum 4 values
        isPrimeCache = new Cache<int, bool>(ItemLoader, 4);

        // If cache is full the least recent used element will be deleted
        isPrimeCache.Behavior = CacheBehavior.RemoveLeastRecentUsedElement;

        // cache is now empty
        DumpCache();

        // reading the cache invokes the loader method
        CheckPrime(13);

        // reading a few more values
        CheckPrime(23);
        CheckPrime(33);
        CheckPrime(43);

        // dumping content
        DumpCache();

        // accessing an already read item does not invoke loader again
        // Now it changes cache order because of the chosen behavior
        CheckPrime(13);
        DumpCache();

        // reading a new element with full cache will delete an old one (now 23)
        CheckPrime(111);
        DumpCache();

        // but accessing a deleted element causes to load it again
        CheckPrime(23);
        DumpCache();

        // dumping some statistics
        Console.WriteLine(isPrimeCache.GetStatistics().ToString());
    }

    // This is the item loader method. It can access database or perform slow calculations.
    // If cache is meant to be serialized it should be a static method rather than an anonymous delegate or lambda expression.
    private static bool ItemLoader(int number)
    {
        Console.WriteLine("Item loading has been invoked for value {0}", number);

        // In this example item loader checks whether the given number is a prime by a not too efficient algorithm.
        if (number <= 1)
            return false;
        if (number % 2 == 0)
            return true;
        int i = 3;
        int sqrt = (int)Math.Floor(Math.Sqrt(number));
        while (i <= sqrt)
        {
            if (number % i == 0)
                return false;
            i += 2;
        }

        return true;
    }

    private static void CheckPrime(int number)
    {
        // cache is used transparently here: indexer is always just read
        bool isPrime = isPrimeCache[number];
        Console.WriteLine("{0} is a prime: {1}", number, isPrime);
    }

    private static void DumpCache()
    {
        Console.WriteLine();
        Console.WriteLine("Cache elements count: {0}", isPrimeCache.Count);
        if (isPrimeCache.Count > 0)
        {
            // enumerating through the cache shows the elements in the evaluation order
            Console.WriteLine("Cache elements:");
            foreach (KeyValuePair<int, bool> item in isPrimeCache)
            {
                Console.WriteLine("\tKey: {0},\tValue: {1}", item.Key, item.Value);
            }
        }

        Console.WriteLine();
    }
}

// This code example produces the following output:
// 
// Cache elements count: 0
// 
// Item loading has been invoked for value 13
// 13 is a prime: True
// Item loading has been invoked for value 23
// 23 is a prime: True
// Item loading has been invoked for value 33
// 33 is a prime: False
// Item loading has been invoked for value 43
// 43 is a prime: True
// 
// Cache elements count: 4
// Cache elements:
// Key: 13,        Value: True
// Key: 23,        Value: True
// Key: 33,        Value: False
// Key: 43,        Value: True
// 
// 13 is a prime: True
// 
// Cache elements count: 4
// Cache elements:
// Key: 23,        Value: True
// Key: 33,        Value: False
// Key: 43,        Value: True
// Key: 13,        Value: True
// 
// Item loading has been invoked for value 111
// 111 is a prime: False
// 
// Cache elements count: 4
// Cache elements:
// Key: 33,        Value: False
// Key: 43,        Value: True
// Key: 13,        Value: True
// Key: 111,       Value: False
// 
// Item loading has been invoked for value 23
// 23 is a prime: True
// 
// Cache elements count: 4
// Cache elements:
// Key: 43,        Value: True
// Key: 13,        Value: True
// Key: 111,       Value: False
// Key: 23,        Value: True
// 
// Cache<Int32, Boolean> cache statistics:
// Count: 4
// Capacity: 4
// Number of writes: 6
// Number of reads: 7
// Number of cache hits: 1
// Number of deletes: 2
// Hit rate: 14,29%
Thread Safety

Members of this type are not safe for multi-threaded operations, though a thread-safe accessor can be obtained for the CacheTKey, TValue by the GetThreadSafeAccessor method. To get a thread-safe wrapper for all members use the AsThreadSafe extension method instead.
Note Note
If a CacheTKey, TValue instance is wrapped into a LockingDictionaryTKey, TValue instance, then the whole cache will be locked during the time when the item loader delegate is being called. If that is not desirable consider to use the GetThreadSafeAccessor method instead with the default arguments and access the cache only via the returned accessor.
See Also

Reference