another-guy - ObEq 1.0.1-b00010

Quick, easy, and correct implementation of object equality in .NET

PM> Install-Package ObEq -Version 1.0.1-b00010 -Source https://www.myget.org/F/another-guy/api/v3/index.json

Copy to clipboard

> nuget.exe install ObEq -Version 1.0.1-b00010 -Source https://www.myget.org/F/another-guy/api/v3/index.json

Copy to clipboard

> dotnet add package ObEq --version 1.0.1-b00010 --source https://www.myget.org/F/another-guy/api/v3/index.json

Copy to clipboard
<PackageReference Include="ObEq" Version="1.0.1-b00010" />
Copy to clipboard
source https://www.myget.org/F/another-guy/api/v3/index.json

nuget ObEq  ~> 1.0.1-b00010
Copy to clipboard

> choco install ObEq --version 1.0.1-b00010 --source https://www.myget.org/F/another-guy/api/v2

Copy to clipboard
Import-Module PowerShellGet
Register-PSRepository -Name "another-guy" -SourceLocation "https://www.myget.org/F/another-guy/api/v2"
Install-Module -Name "ObEq" -RequiredVersion "1.0.1-b00010" -Repository "another-guy" -AllowPreRelease
Copy to clipboard

Synopsis

ObEq (from ObjectEquality) provides basic implementation for GetHashCode and Equals methods.

Code Example

Let's assume there is a class Sample

public class Sample<T>
{
    private readonly T field1;
    private readonly int field2;

    // Constructor(s)...

    // Other methods and properties...
}

If we need this class to implement GetHashCode() and Equals() methods, it could be easily achieved using ObEq's EqualityHelper class.

Implementing IMemberwiseComparable

First step is to make the target type implement the IMemberwiseComparable interface. This will enforce the type to define EqualityMembers property refers to all fields that should be used as equality members.

IMPORTANT The referred fields should be declared as readonly otherwise the calculated hash code value can change every time any field value is modified. While it's technically possible to use not readonly (i.e. mutable) fields, it's not recommended because it can break code that relies on object's hashcode consistency. Dictionary is an example of a collection that will not tolerate hash code volatility. See Eric Lippert's blog post and StackOverflow discussion for more details.

Second step is to make the Equals() and GetHashCode() delegate result calculation to EqualityHelper class. The simplest code will look as following:

namespace ObEq.Tests
{
    public class Sample<T> : IMemberwiseComparable
    {
        private readonly T field1;
        private readonly int field2;

        public Sample(T1 t, int i)
        {
			this.field1 = t;
			this.field2 = i;
        }

        public override bool Equals(object other)
        {
            return EqualityHelper.CalculateEquals(this, other as IMemberwiseComparable);
        }

        public override int GetHashCode()
        {
            return EqualityHelper.CalculateHashCode(EqualityMembers);
        }

        public object[] EqualityMembers => new[] { field1, field2 };
    }
}

or wihtout implementing IMemberwiseComparable

Otherwise, you may write a slightly different variation of the code. In this scenario you have more control over equality calculation. Also, there is no need to implement the IMemberwiseComparable interface.

Notice that EqualityHelperReferencesEqual(object1, object2) is used to check whether the references are same or not; whereas EqualityHelperAllMembersEqual(equalityMembers1, equalityMembers2) is the method that does the actual fieldwise comparison for two objects.

private object[] EqualityMembers => new[] { field1, field2 };

public bool Equals(Sample<T> other)
{
	return EqualityHelper.AllMembersEqual(this.EqualityMembers, other.EqualityMembers);
}

public override bool Equals(object other)
{
	return EqualityHelper.ReferencesEqual(this, other) ??
		EqualityHelper.AllMembersEqual(this.EqualityMembers, ((Sample<T1>)other).EqualityMembers);
}

public override int GetHashCode()
{
	return EqualityHelper.CalculateHashCode(EqualityMembers);
}

References

MSDN page about GetHashCode()

MSDN page about Equals() method

Installation

ObEq is a available in a form of a NuGet package. Follow regular installation process to bring it to your project. https://www.nuget.org/packages/ObEq/

Tests

Unit tests are available in ObEq.Tests project.

License

The code is distributed under the MIT license.

Reporting an Issue

Reporting an issue, proposing a feature, or asking a question are all great ways to improve software quality.

Here are a few important things that package contributors will expect to see in a new born GitHub issue:

  • the relevant version of the package;
  • the steps to reproduce;
  • the expected result;
  • the observed result;
  • some code samples illustrating current inconveniences and/or proposed improvements.

Contributing

Contribution is the best way to improve any project!

  1. Fork it!
  2. Create your feature branch (git checkout -b my-new-feature).
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

...or follow steps described in a nice fork guide by Karl Broman

  • .NETStandard 1.6
    • NETStandard.Library (>= 1.6.0)
  • .NETStandard 1.6: 1.6.0.0

Owners

another-guy

Authors

Igor Soloydenko

Project URL

https://github.com/another-guy/ObEq

License

MIT

Tags

GetHashCode,HashCode,Equals

Info

17 total downloads
2 downloads for version 1.0.1-b00010
Download (3.67 KB)
Found on the current feed only

Package history

Version Size Last updated Downloads Mirrored?
2.0.0 3.96 KB Mon, 19 Dec 2016 03:35:14 GMT 2
2.0.0-b00019 3.97 KB Fri, 16 Jun 2017 22:04:22 GMT 0
2.0.0-b00018 3.97 KB Fri, 16 Jun 2017 17:45:06 GMT 0
2.0.0-b00016 3.97 KB Mon, 19 Dec 2016 03:34:08 GMT 2
1.1.0 3.88 KB Sat, 06 Aug 2016 22:19:51 GMT 2
1.1.0-b00014 3.89 KB Sun, 07 Aug 2016 22:30:36 GMT 3
1.1.0-b00012 3.88 KB Sat, 06 Aug 2016 22:18:07 GMT 4
1.0.1-b00011 3.67 KB Sat, 06 Aug 2016 01:31:29 GMT 2
1.0.1-b00010 3.67 KB Sat, 06 Aug 2016 01:30:15 GMT 2