Comments (8)
The Default
comparer will forward to the IComparable<T>
implementation. What behavior were you expecting?
from comparers.
This throws an exception
var c1 = new Component
{
Weight = 0.7,
AccWeight = 0.2
};
var c2 = new Component
{
Weight = 0.7,
AccWeight = 0.2
};
var result = c1.Equals(c2);
from comparers.
Yes, the Default
comparer forwards to IComparable<T>
, which is implemented by the DefaultComparer
, which is just Default
, which forwards to IComparable<T>
, ... So of course you're going to get a stack overflow exception.
Again, what behavior were you expecting?
from comparers.
I expected it to compare one property at a time and return true.
from comparers.
I may be wrong but I don't think using Equals
method should never throw StackOverflowException
regardless of implementation. It should return either true or false.
from comparers.
@amir734jj: Nito.Comparers does not reflect over all properties of types. That's rarely the desired behavior.
The Default()
comparer is behaving appropriately. You would have the same exact problem with the .NET Comparer<T>.Default
or EqualityComparer<T>.Default
.
from comparers.
I understand. I am passionate about this subject because I spend too much time daily writing and maintaining Equals
and GetHashCode
methods. We don't necessarily need to use reflection every time. We can just create an Expression and compile it once.
public class Component
{
public double AccumulatedWeight { get; set; }
public double Weight { get; set; }
public Nested NestedRef { get; set; }
}
public class Nested
{
public double NestedProp { get; set; }
}
class Program
{
static void Main(string[] args)
{
var c1 = new Component
{
Weight = 0.7,
AccumulatedWeight = 0.2,
NestedRef = new Nested
{
NestedProp = 223
}
};
var c2 = new Component
{
Weight = 0.7,
AccumulatedWeight = 0.2,
NestedRef = new Nested
{
NestedProp = 223
}
};
var result = BuildEquals<Component>()(c1, c2);
Console.WriteLine(result);
}
public static Func<T, T, bool> BuildEquals<T>()
{
return ((Expression<Func<T, T, bool>>) BuildEquals(typeof(T))).Compile();
}
public static Expression BuildEquals(Type type)
{
bool IsComplexType(Type nestedType)
{
return !nestedType.Namespace.StartsWith("System.Collections") && nestedType.IsClass;
}
var arg1 = Expression.Parameter(type);
var arg2 = Expression.Parameter(type);
var body = type
.GetProperties()
.Select(x =>
{
if (IsComplexType(x.PropertyType))
{
return (Expression) Expression.Invoke(BuildEquals(x.PropertyType),
Expression.Property(arg1, x.Name),
Expression.Property(arg2, x.Name));
}
else
{
return Expression.Equal(Expression.Property(arg1, x.Name), Expression.Property(arg2, x.Name));
}
})
.Aggregate((x, y) => Expression.And(x, y));
return Expression.Lambda(body, arg1, arg2);
}
from comparers.
You can use a similar approach to BuildEquals
along with Nito.Comparers as such:
public static IFullEqualityComparer<T> BuildAllMembersEqualityComparer<T>()
{
var result = EqualityComparerBuilder.For<T>().Null();
var type = typeof(T);
var parameter = Expression.Parameter(type);
foreach (var prop in type.GetProperties())
{
var expression = Expression.Property(parameter, prop.Name);
dynamic selector = Expression.Lambda(expression, parameter).Compile();
dynamic childComparer = null;
if (IsComplexType(prop.PropertyType))
childComparer = ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(prop.PropertyType).Invoke(null, null);
result = EqualityComparerExtensions.ThenEquateBy(result, selector, childComparer);
}
return result;
bool IsComplexType(Type nestedType) => !nestedType.Namespace.StartsWith("System.Collections") && nestedType.IsClass;
}
This code takes a similar approach as run-time comparers: starting with Null
(everything is equivalent), and adding a ThenEquateBy
clause for each member.
Using Nito.Comparers in this way, the same lambda expressions are used to implement both Equals
and GetHashCode
.
from comparers.
Related Issues (20)
- Calling Equals with arguments of different types HOT 5
- specialNullHandling parameter ignored HOT 6
- Better syntax for wrapping other comparers HOT 1
- Remove NotImplementedException
- Revisit GetHashCode(null) behavior HOT 1
- Fix EqualityComparerBase
- Finish invariant tests for all comparers
- Restrict Reference extension method to reference types
- Remove BinarySearch extensions
- String comparers HOT 4
- All-Members Comparer
- Float/double equality comparers HOT 4
- Consider new hash algorithm HOT 1
- Utf8StringComparer? HOT 1
- NaturalStringComparer HOT 1
- Static constructors not always run
- Collection comparer without order HOT 4
- Provide the ability to take a compare an item using delegates HOT 2
- Use for comparing by interface?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from comparers.