{"id":15882505,"url":"https://github.com/another-guy/obeq","last_synced_at":"2025-07-01T10:05:51.970Z","repository":{"id":89024283,"uuid":"63979351","full_name":"another-guy/ObEq","owner":"another-guy","description":"Quick, easy, and correct implementation of object equality in .NET","archived":false,"fork":false,"pushed_at":"2017-06-16T22:03:25.000Z","size":36,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-20T10:43:06.502Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/another-guy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-07-22T19:50:20.000Z","updated_at":"2016-12-19T03:33:28.000Z","dependencies_parsed_at":"2023-06-16T10:45:48.240Z","dependency_job_id":null,"html_url":"https://github.com/another-guy/ObEq","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/another-guy/ObEq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/another-guy%2FObEq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/another-guy%2FObEq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/another-guy%2FObEq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/another-guy%2FObEq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/another-guy","download_url":"https://codeload.github.com/another-guy/ObEq/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/another-guy%2FObEq/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262941545,"owners_count":23388149,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-06T04:04:06.518Z","updated_at":"2025-07-01T10:05:51.944Z","avatar_url":"https://github.com/another-guy.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Synopsis\n\nObEq (from ObjectEquality) provides basic implementation for GetHashCode and Equals methods.\n\n## Code Example\n\nLet's assume there is a class Sample\u003cT\u003e that has two fields.\nIt could be defined this way:\n\n```cs\npublic class Sample\u003cT\u003e\n{\n    private readonly T field1;\n    private readonly int field2;\n\n    // Constructor(s)...\n\n    // Other methods and properties...\n}\n```\n\nIf we need this class to implement GetHashCode() and Equals() methods, it could be easily achieved using ObEq's EqualityHelper class.\n\n### Implementing IMemberwiseComparable\n\nFirst step is to make the target type implement the `IMemberwiseComparable` interface.\nThis will enforce the type to define EqualityMembers property refers to all fields that should be used as equality members.\n\n**IMPORTANT**\nThe referred fields should be declared as `readonly` otherwise the calculated hash code value can change every time any field value is modified.\nWhile 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.\nDictionary is an example of a collection that will not tolerate hash code volatility.\nSee [Eric Lippert's blog post](https://blogs.msdn.microsoft.com/ericlippert/2011/02/28/guidelines-and-rules-for-gethashcode/) and [StackOverflow discussion](http://stackoverflow.com/questions/4718009/mutable-objects-and-hashcode) for more details.\n\nSecond step is to make the Equals() and GetHashCode() delegate result calculation to EqualityHelper class.\nThe simplest code will look as following:\n\n```cs\nnamespace ObEq.Tests\n{\n    public class Sample\u003cT\u003e : IMemberwiseComparable\n    {\n        private readonly T field1;\n        private readonly int field2;\n\n        public Sample(T1 t, int i)\n        {\n\t\t\tthis.field1 = t;\n\t\t\tthis.field2 = i;\n        }\n\n        public override bool Equals(object other)\n        {\n            return EqualityHelper.CalculateEquals(this, other as IMemberwiseComparable);\n        }\n\n        public override int GetHashCode()\n        {\n            return EqualityHelper.CalculateHashCode(EqualityMembers);\n        }\n\n        public object[] EqualityMembers =\u003e new[] { field1, field2 };\n    }\n}\n```\n\n### or wihtout implementing IMemberwiseComparable\n\nOtherwise, you may write a slightly different variation of the code.\nIn this scenario you have more control over equality calculation.\nAlso, there is no need to implement the IMemberwiseComparable interface.\n\nNotice that EqualityHelper::ReferencesEqual(object1, object2) is used to check whether the references are same or not;\nwhereas EqualityHelper::AllMembersEqual(equalityMembers1, equalityMembers2) is the method that does the actual fieldwise comparison for two objects.\n\n```cs\nprivate object[] EqualityMembers =\u003e new[] { field1, field2 };\n\npublic bool Equals(Sample\u003cT\u003e other)\n{\n\treturn EqualityHelper.AllMembersEqual(this.EqualityMembers, other.EqualityMembers);\n}\n\npublic override bool Equals(object other)\n{\n\treturn EqualityHelper.ReferencesEqual(this, other) ??\n\t\tEqualityHelper.AllMembersEqual(this.EqualityMembers, ((Sample\u003cT1\u003e)other).EqualityMembers);\n}\n\npublic override int GetHashCode()\n{\n\treturn EqualityHelper.CalculateHashCode(EqualityMembers);\n}\n```\n\n## References\n\n[MSDN page about GetHashCode()](https://msdn.microsoft.com/en-us/library/system.string.gethashcode(v=vs.110).aspx)\n\n[MSDN page about Equals() method](https://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx)\n\n## Installation\n\nObEq is a available in a form of a NuGet package.\nFollow regular installation process to bring it to your project.\nhttps://www.nuget.org/packages/ObEq/\n\n## Tests\n\nUnit tests are available in ObEq.Tests project.\n\n## License\n\nThe code is distributed under the MIT license.\n\n## Reporting an Issue\n\nReporting an issue, proposing a feature, or asking a question are all great ways to improve software quality.\n\nHere are a few important things that package contributors will expect to see in a new born GitHub issue:\n* the relevant version of the package;\n* the steps to reproduce;\n* the expected result;\n* the observed result;\n* some code samples illustrating current inconveniences and/or proposed improvements.\n\n## Contributing\n\nContribution is the best way to improve any project!\n\n1. Fork it!\n2. Create your feature branch (```git checkout -b my-new-feature```).\n3. Commit your changes (```git commit -am 'Added some feature'```)\n4. Push to the branch (```git push origin my-new-feature```)\n5. Create new Pull Request\n\n...or follow steps described in a nice [fork guide](http://kbroman.org/github_tutorial/pages/fork.html) by Karl Broman\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanother-guy%2Fobeq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanother-guy%2Fobeq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanother-guy%2Fobeq/lists"}