-
-
Notifications
You must be signed in to change notification settings - Fork 501
Fix and cleanup GetHashCode and Equals #797
Conversation
src/ImageProcessor.Plugins.Cair/Imaging/ContentAwareResizeLayer.cs
Outdated
Show resolved
Hide resolved
var a = new List<int> { 1, 2, 3 };
var b = new List<int> { 1, 2, 3 };
EqualityComparer<List<int>>.Default.Equals(a, b); // False |
src/ImageProcessor.Plugins.Cair/Imaging/ContentAwareResizeLayer.cs
Outdated
Show resolved
Hide resolved
I can confirm using var a = new List<int> { 1, 2, 3 };
var b = new List<int> { 1, 2, 3 };
a.Equals(b); // False
a.SequenceEqual(b); // True
a.GetHashCode() == b.GetHashCode(); // False, as different instances return different hash codes, even if the items are the same Equal items should return the same hash code (although the reverse isn't always true because of hash collisions), which isn't always the case in the current codebase. Microsoft has added a A quick fix would be to ensure equality is checked individually per property (with support for null values and collections) and just skip the collections in |
We copied the source for HashCode into the the SixLabors codebase for unsupported frameworks and use type forwarding to avoid conflict. Perhaps we can simply do the same here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've checked all GetHashCode
methods and ResizeLayer
is the only class that has collections that could be included. Not including all properties shouldn't cause major problems, so I'm fine with the possibility of more hash collisions for non-equal objects.
I've also added some additional comments for explanation and to review 👍
I've updated the test to handle the fixed @JimBobSquarePants If you can review whether the unresolved comments are okay, I think this is ready to get merged! |
Note that merging this after PR #796 will result in a conflict on public bool Equals(ResizeLayer other) => other != null
&& this.Size == other.Size
&& this.MaxSize == other.MaxSize
&& (this.RestrictedSizes == null || other.RestrictedSizes == null ? this.RestrictedSizes == other.RestrictedSizes : this.RestrictedSizes.SequenceEqual(other.RestrictedSizes))
&& this.ResizeMode == other.ResizeMode
&& this.AnchorPosition == other.AnchorPosition
&& this.Upscale == other.Upscale
&& this.Center == other.Center
&& this.AnchorPoint == other.AnchorPoint;
public override int GetHashCode() => (this.Size, this.MaxSize, this.ResizeMode, this.AnchorPosition, this.Upscale, this.Center, this.AnchorPoint).GetHashCode(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work. 👍
Prerequisites
Description
This fixes some possible
NullReferenceException
s in theEquals
implementations and usesValueTuple
to generate the hash codes, as that's a lot easier, cleaner and heavily optimized: