Ddth.Signum
0.0.3
dotnet add package Ddth.Signum --version 0.0.3
NuGet\Install-Package Ddth.Signum -Version 0.0.3
<PackageReference Include="Ddth.Signum" Version="0.0.3" />
<PackageVersion Include="Ddth.Signum" Version="0.0.3" />
<PackageReference Include="Ddth.Signum" />
paket add Ddth.Signum --version 0.0.3
#r "nuget: Ddth.Signum, 0.0.3"
#:package Ddth.Signum@0.0.3
#addin nuget:?package=Ddth.Signum&version=0.0.3
#tool nuget:?package=Ddth.Signum&version=0.0.3
Lightweight .NET library for calculating checksums and object fingerprints of any .NET object - from primitives and collections to arbitrary objects.
Features
- Works with any object. Operates at the interface level (
IList,ISet,IDictionary, ...) rather than concrete implementations, and falls back to reflection for arbitrary objects. - Type-aware, value-stable checksums.
- Integer types with the same value share a checksum (e.g.
(int)5,(long)5,(byte)5). floatanddoubleof the same value share a checksum;Halfanddecimalare distinct.- Different families with the "same" value differ (e.g.
(int)5≠(float)5≠(decimal)5).
- Integer types with the same value share a checksum (e.g.
- Structure-aware composition.
- Ordered collections (arrays,
IList,IEnumerable) are order-sensitive. - Unordered collections (
ISet,IDictionary) are order-insensitive.
- Ordered collections (arrays,
- Customizable.
- Plug in your own hash function via
IHasher; the default is a fast, non-cryptographicXxHash128.XxHash3andCrc32hashers are also provided out of the box. - Implement
ISignumFingerprintableto control how a type contributes to its fingerprint. - Exclude individual members with
[SignumIgnore].
- Plug in your own hash function via
- Safe by default. Reference cycles are detected and handled gracefully.
Usage
$ dotnet add package Ddth.Signum
Use the static Signum helper for the common case:
using Ddth.Signum;
byte[] checksum = Signum.Checksum(myObject);
string hex = Signum.ChecksumHex(myObject);
Signum.Checksum accepts anything:
Signum.ChecksumHex(42); // primitives
Signum.ChecksumHex(new[] { 1, 2, 3 }); // ordered collections
Signum.ChecksumHex(new HashSet<int> { 1, 2, 3 }); // unordered collections
Signum.ChecksumHex(new { Name = "Alice", Age = 30 }); // arbitrary objects
Same value, same checksum - regardless of the concrete integer type or collection order:
Signum.ChecksumHex(5) == Signum.ChecksumHex(5L); // true (integer family)
var a = new Dictionary<string, int> { ["a"] = 1, ["b"] = 2 };
var b = new Dictionary<string, int> { ["b"] = 2, ["a"] = 1 };
Signum.ChecksumHex(a) == Signum.ChecksumHex(b); // true (order-insensitive)
var list1 = new List<int> { 1, 2, 3 };
var list2 = new List<int> { 3, 2, 1 };
Signum.ChecksumHex(list1) == Signum.ChecksumHex(list2); // false (order matters)
Using a custom hash function
The library ships three hashers (all from System.IO.Hashing): XxHash128Hasher (default,
16-byte), XxHash3Hasher (8-byte) and Crc32Hasher (4-byte). Select one via
FingerprintOptions.HasherFactory, or via the optional parameter on the Signum helper:
// Use a built-in hasher through the static helper. Each hasher exposes a shared
// `Factory` delegate, which lets the Signum helper cache and reuse a single
// Fingerprinter per hasher type:
string hex = Signum.ChecksumHex(myObject, XxHash3Hasher.Factory);
Provide your own IHasher to use any other algorithm:
using System.IO.Hashing;
using Ddth.Signum;
public sealed class Crc64Hasher : IHasher
{
private readonly Crc64 _inner = new();
public int HashLengthInBytes => _inner.HashLengthInBytes;
public void Append(ReadOnlySpan<byte> data) => _inner.Append(data);
public void GetHashAndReset(Span<byte> destination) => _inner.GetHashAndReset(destination);
}
var fingerprinter = new Fingerprinter(new FingerprintOptions
{
HasherFactory = () => new Crc64Hasher()
});
byte[] checksum = fingerprinter.Compute(myObject);
Controlling how objects are fingerprinted
By default, an unknown object is fingerprinted over its public properties and fields. Exclude a
member with [SignumIgnore]:
public sealed class User
{
public string Name { get; set; }
[SignumIgnore]
public DateTime LastAccessed { get; set; } // ignored in the fingerprint
}
For full control, implement ISignumFingerprintable:
public sealed class Money : ISignumFingerprintable
{
public decimal Amount { get; set; }
public string Currency { get; set; }
public void WriteFingerprint(IFingerprintWriter writer)
{
writer.Write(Amount).Write(Currency);
}
}
License
This package is licensed under the MIT License - see the LICENSE.md file for details.
Contributing & Support
Feel free to create pull requests or issues to report bugs or suggest new features.
| Product | Versions 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 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. |
-
net10.0
- System.IO.Hashing (>= 8.0.0)
-
net6.0
- System.IO.Hashing (>= 8.0.0)
-
net8.0
- System.IO.Hashing (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
### Fixed/Improvements
- Impr: Expose shared static Factory on XxHash128Hasher, XxHash3Hasher and Crc32Hasher for cached reuse via Signum.