DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="4.7.1" />

 SoftReferenceOptions

public class SoftReferenceOptions
Allows to configure behavior of SoftReference<T>.
using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext.Runtime { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public class SoftReferenceOptions { private readonly int collectionCount; private readonly long memoryLimit = 9223372036854775807; private readonly double memoryThreshold = 1; public static SoftReferenceOptions Default { get; } = new SoftReferenceOptions(); public int CollectionCount { get { return collectionCount; } set { if (value <= 0) throw new ArgumentOutOfRangeException("value"); collectionCount = value; } } public long MemoryLimit { get { return memoryLimit; } set { if (value <= 0) throw new ArgumentOutOfRangeException("value"); memoryLimit = value; } } public double MemoryThreshold { get { return memoryThreshold; } set { if (!double.IsFinite(value) || !value.IsBetween(0, 1, BoundType.RightClosed)) throw new ArgumentOutOfRangeException("value"); memoryThreshold = value; } } internal bool KeepTracking(object target) { int generation = GC.GetGeneration(target); if (generation >= GC.MaxGeneration) { if (GC.CollectionCount(generation) <= collectionCount) return CheckLimits(generation); return false; } return true; } private bool CheckLimits(int generation) { GCMemoryInfo info = GC.GetGCMemoryInfo(); if (info.Index != 0) { if (CheckMemoryLimit(generation, ref info)) return CheckMemoryThreshold(ref info); return false; } return true; } private bool CheckMemoryThreshold([In] [IsReadOnly] ref GCMemoryInfo info) { return (double)info.MemoryLoadBytes <= (double)info.HighMemoryLoadThresholdBytes * memoryThreshold; } private bool CheckMemoryLimit(int generation, [In] [IsReadOnly] ref GCMemoryInfo info) { if (memoryLimit != 9223372036854775807) { ReadOnlySpan<GCGenerationInfo> generationInfo; ReadOnlySpan<GCGenerationInfo> readOnlySpan = generationInfo = info.GenerationInfo; if (readOnlySpan.Length > generation) return generationInfo[generation].SizeAfterBytes < memoryLimit; } return true; } } }