armat.utils 2.1.0

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

Armat Utilities

NuGet License: MIT

Armat.Utils is a comprehensive .NET 10.0 library providing reusable utilities for building robust .NET applications. It includes thread-safe counters, specialized collections, serialization helpers, and useful extension methods.

Installation

dotnet add package armat.utils

Or via NuGet Package Manager:

Install-Package armat.utils

Features

🔢 Counters (Armat.Utils)

Thread-safe counter implementations for synchronization and control flow:

  • Counter - A thread-safe 64-bit counter with atomic increment/decrement operations. Fires pre and post modification events when the counter value changes.

  • LockCounter - A thread-safe reentrant lock counter. Blocks operations while locked (value > 0) and fires events on lock/unlock. Includes CreateLocker() method to automatically manage lock scope with IDisposable pattern.

  • ControlledActionInvoker - Extends LockCounter to control method invocations. Blocks action execution while locked and optionally triggers deferred execution upon unlock.

📚 Collections (Armat.Collections)

High-performance specialized collection types:

  • ConcurrentList<T> - Thread-safe list implementation using ReaderWriterLockSlim for efficient concurrent access. Implements IList<T>, IReadOnlyList<T>, and IDisposable.

  • IndigentList<T> - Memory-efficient list optimized for collections with fewer than 2 elements. Avoids array allocation when possible, reducing memory overhead for small collections.

  • ListDictionary<TKey, TValue> - Ordered dictionary implementing both IDictionary<TKey, TValue> and IList<TValue> interfaces. Maintains insertion order while providing O(1) key-based lookups.

  • IndexedList<T> - A list that can be indexed by multiple fields of the items simultaneously. Supports various indexing strategies:

    • DictionaryIndex - Hash-based single field indexing
    • MultiDictionaryIndex - Hash-based multi-field indexing
    • Additional index types available for different access patterns
  • SegmentedStringDictionary - Dictionary with hierarchical segment-based keys. Keys are grouped by segments (e.g., Key@Segment1|Segment2), useful for storing categorized properties and settings. Implements ISegmentedStringDictionary interface for segment-based access patterns.

💾 Serialization (Armat.Serialization)

Simplified serialization utilities:

  • IPackable / IPackage - Interfaces for custom serialization. Types implement IPackable.Pack() to return serializable packages, and IPackage.Unpack() to reconstruct objects. Includes extension methods for batch packing / unpacking collections.

  • ITypeLocator - Interface for type resolution during deserialization based on assembly and type names. Useful for deserializing polymorphic types across assemblies.

  • JsonSerializer - Static helper class for JSON serialization / deserialization. Supports serialization to string, file and stream, and deserialization from appropriate constructs.

  • XmlSerializer - Static helper class for XML serialization / deserialization. Supports serialization to string, file, stream, XmlDocument and XmlElement, and deserialization from appropriate constructs.

  • XmlFileElementReference - Utility for reading / writing specific XML elements within a file at a given XPath. Useful for targeted XML element manipulation without loading entire documents.

⚠️ Security note: JsonSerializer / XmlSerializer embed type information in the payload and instantiate the type named there during deserialization. Never deserialize untrusted input with the default type locator — pass an allow-listing ITypeLocator to restrict the set of permitted types.

🔧 Extensions (Armat.Utils.Extensions)

Convenient extension methods:

  • ByteArray - Extensions for byte[]:

    • ContentsEquals() - Compare byte array contents with optimized 8-byte chunk processing
    • Copy and bitwise operations
  • ContentComparer - Compare collection contents for equality:

    • ContentsEquals() for IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<T>, and IEnumerable<T>
    • Supports custom IEqualityComparer<T> for value comparison
  • ExceptionHelpers - Navigate exception hierarchies:

    • As<T>() and Is<T>() for Exception and AggregateException
    • Configurable lookup modes: TheOnlyOne, AnyMatch, First, Last, FirstIfAllSameType, LastIfAllSameType
  • RWLockers - Simplified ReaderWriterLockSlim usage with IDisposable lock objects:

    • CreateRLocker() - Read lock
    • CreateURLocker() - Upgradeable read lock
    • CreateWLocker() - Write lock
    • Automatic lock release on dispose

Usage Examples

Counter Example

using Armat.Utils;

var counter = new Counter();
long value = counter.Increment(); // Thread-safe increment

LockCounter Example

using Armat.Utils;

var lockCounter = new LockCounter();
lockCounter.Lock();
try {
    // Critical section
}
finally {
    lockCounter.Unlock();
}

// Or use disposable pattern:
using (lockCounter.CreateLocker()) {
    // Automatically locked
} // Automatically unlocked

IndexedList Example

using Armat.Collections;

var list = new IndexedList<Person>();
var nameIndex = list.CreateHashIndex("NameIndex", p => p.Name, StringComparer.OrdinalIgnoreCase);

list.Add(new Person { Name = "John", Age = 30 });
var john = nameIndex["John"]; // O(1) lookup

ReaderWriterLockSlim Extensions

using Armat.Utils.Extensions;

var rwLock = new ReaderWriterLockSlim();

// Read lock
using (rwLock.CreateRLocker()) {
    // Read operations
}

// Write lock
using (rwLock.CreateWLocker()) {
    // Write operations
}

Requirements

  • .NET 10.0 or later

License

This project is licensed under the MIT License - see the LICENSE.txt file for details.

Version History

Per-release details are maintained in ReleaseNotes.md — shipped inside this package and available at github.com/ar-mat/Utilities/blob/main/ReleaseNotes.md.

Version 2.1.0

Bug-fix release with breaking API cleanups; retargeted to .NET 10.0 (from .NET 8.0):

  • Retargeted to .NET 10.0 — projects on .NET 8/9 can no longer reference this package version
  • Fixed inverted Counter inequality operator and truncating Int32 comparisons
  • Fixed IndexedList index APIs returning internal storage indexes (IndexOfValue, IndexOfItem, IIndex.Remove(KeyValuePair), ListDictionary.Remove/IndexOf by value)
  • Fixed unique index corruption on rejected duplicate-key updates
  • JsonSerializer.ToFile now truncates existing files; XmlFileElementReference.SaveXmlElement create path fixed
  • Duplicate index keys now surface as ArgumentException (previously OperationCanceledException)
  • ContentsEquals dictionary overloads are IReadOnlyDictionary-only (IDictionary overloads removed as ambiguous)
  • ListDictionary key-based removal renamed to RemoveByKey; Values returns a read-only view
  • IndexedList / ListDictionary now implement IDisposable (synchronized mode) instead of a finalizer
  • ReIndex is now non-generic; the unused-type-parameter overloads were removed

Version 2.0.1

Release targeting .NET 8.0


More utilities will come later...

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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.
  • net10.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on armat.utils:

Package Downloads
armat.threading

C# class library for developing multithreaded applications. It can be used as an alternative to .Net System.Threading.Tasks library to support multiple schedulers within a context of a single application.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.1.0 106 10/6/2026
2.0.3 565 11/19/2025
2.0.2 493 11/18/2025
2.0.1 318 9/22/2025
2.0.0 321 9/19/2025
1.0.1 280 9/23/2024
1.0.0 393 4/6/2024