C0deGeek.ObjectCompare
1.0.1
dotnet add package C0deGeek.ObjectCompare --version 1.0.1
NuGet\Install-Package C0deGeek.ObjectCompare -Version 1.0.1
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="C0deGeek.ObjectCompare" Version="1.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add C0deGeek.ObjectCompare --version 1.0.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: C0deGeek.ObjectCompare, 1.0.1"
#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.
// Install C0deGeek.ObjectCompare as a Cake Addin #addin nuget:?package=C0deGeek.ObjectCompare&version=1.0.1 // Install C0deGeek.ObjectCompare as a Cake Tool #tool nuget:?package=C0deGeek.ObjectCompare&version=1.0.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
ObjectComparison
A high-performance, extensible .NET library for deep object comparison with support for complex types, collections, and dynamic objects.
Features
- Deep comparison of objects with circular reference detection
- Object snapshot capability with intelligent cloning
- Support for custom comparison and cloning logic
- Collection comparison with order-sensitive and order-insensitive modes
- Dynamic object comparison support (ExpandoObject, DynamicObject)
- Floating-point comparison with configurable precision
- Advanced type handling:
- Nullable types
- Value types with safe default initialization
- Reference types with proper null handling
- Custom type cloning
- Thread-safe caching:
- Type metadata caching
- Expression compilation caching
- Property access optimization
- Comprehensive comparison results with detailed differences
- Expression tree-based property access for performance
- Support for private field comparison
- Configurable maximum depth and object count limits
Installation
dotnet add package ObjectComparison
Quick Start
// Create a comparer with default configuration
var comparer = new ObjectComparer();
// Compare two objects
var result = comparer.Compare(obj1, obj2);
if (!result.AreEqual)
{
foreach (var difference in result.Differences)
{
Console.WriteLine(difference);
}
}
// Take a snapshot for later comparison
var snapshot = comparer.TakeSnapshot(originalObject);
Object Snapshots
The library provides powerful snapshot capabilities with intelligent cloning.
Basic Snapshot Usage
// Create an object and take a snapshot
var person = new Person
{
Name = "John Doe",
Age = 30,
Hobbies = new List<string> { "Reading", "Gaming" }
};
var comparer = new ObjectComparer();
var snapshot = comparer.TakeSnapshot(person);
// Make changes to the original object
person.Age = 31;
person.Hobbies.Add("Cooking");
// Compare current state with snapshot
var result = comparer.Compare(person, snapshot);
Custom Type Cloning
var config = new ComparisonConfig
{
CustomCloners = new Dictionary<Type, Func<object, object>>
{
{
typeof(DateTime),
obj => ((DateTime)obj).Date // Clone only the date part
},
{
typeof(StringBuilder),
obj => new StringBuilder(((StringBuilder)obj).ToString())
}
}
};
var comparer = new ObjectComparer(config);
Type Handling
// Value Types
struct Point { public int X, Y; }
var point = new Point { X = 1, Y = 2 };
var snapshot = comparer.TakeSnapshot(point); // Creates proper value copy
// Nullable Types
int? nullableValue = 42;
var snapshot = comparer.TakeSnapshot(nullableValue); // Preserves null state
// Collections
var list = new List<Point> { new() { X = 1, Y = 2 } };
var snapshot = comparer.TakeSnapshot(list); // Deep clones elements
Advanced Configuration
var config = new ComparisonConfig
{
// Comparison Options
ComparePrivateFields = true,
DeepComparison = true,
IgnoreCollectionOrder = true,
// Precision Settings
DecimalPrecision = 4,
FloatingPointTolerance = 1e-10,
UseRelativeFloatingPointComparison = true,
// Null Handling
NullValueHandling = NullHandling.Loose,
// Performance Options
MaxDepth = 10,
MaxObjectCount = 10000,
UseCachedMetadata = true,
// Property Options
ExcludedProperties = new HashSet<string> { "CachedValue", "LastModified" },
CompareReadOnlyProperties = true,
// Type-Specific Options
CustomComparers = new Dictionary<Type, ICustomComparer>(),
CollectionItemComparers = new Dictionary<Type, IEqualityComparer>(),
// Diagnostics
TrackPropertyPaths = true,
Logger = loggerFactory.CreateLogger<ObjectComparer>()
};
Error Handling
try
{
var result = comparer.Compare(obj1, obj2);
}
catch (ComparisonException ex) when (ex.Path != null)
{
Console.WriteLine($"Comparison failed at path: {ex.Path}");
Console.WriteLine($"Error: {ex.Message}");
}
catch (ArgumentException ex)
{
Console.WriteLine($"Invalid argument: {ex.Message}");
}
Common Exceptions
ComparisonException
: General comparison failuresArgumentException
: Invalid types or configurationsInvalidOperationException
: Operation not supported for typeNotSupportedException
: Unsupported type or operation
Performance Optimization
Caching
// Enable all caching features
var config = new ComparisonConfig
{
UseCachedMetadata = true,
TrackPropertyPaths = false // Disable for better performance
};
// Pre-compile frequently used types
TypeCache.GetMetadata(typeof(MyFrequentType), true);
Memory Management
// Limit object graph traversal
var config = new ComparisonConfig
{
MaxDepth = 5,
MaxObjectCount = 1000,
ExcludedProperties = new HashSet<string> { "LargeCollection", "CachedData" }
};
Collection Handling
// Fast collection comparison for simple types
var config = new ComparisonConfig
{
IgnoreCollectionOrder = true, // Uses optimized comparison
CollectionItemComparers = new Dictionary<Type, IEqualityComparer>
{
{ typeof(int), EqualityComparer<int>.Default }
}
};
Thread Safety
The library uses several thread-safe mechanisms:
- Concurrent collections for caches
- Immutable configuration objects
- Thread-local contexts for comparison state
- Lock-free algorithms where possible
Safe Concurrent Usage
// Create once and reuse
private static readonly ObjectComparer SharedComparer = new();
// Safe for concurrent use
public async Task CompareAsync(object obj1, object obj2)
{
await Task.Run(() => SharedComparer.Compare(obj1, obj2));
}
Best Practices
- Reuse
ObjectComparer
instances - Configure appropriate depth limits
- Use custom comparers for complex types
- Enable caching for repeated comparisons
- Handle circular references appropriately
- Use type-specific equality comparers
- Consider memory usage with large object graphs
- Implement proper error handling
- Use logging for troubleshooting
- Test with representative data sets
Contributing
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
License
This project is licensed under the MIT License - see the LICENSE.md file for details.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | 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. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net8.0
- Microsoft.Extensions.Logging (>= 8.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.