Skip to content

fix: use case-insensitive comparer in IEnum GetHashCode#1797

Open
TabishRiazBajwa wants to merge 2 commits into
Adyen:mainfrom
TabishRiazBajwa:fix/ienum-gethashcode-case-insensitive
Open

fix: use case-insensitive comparer in IEnum GetHashCode#1797
TabishRiazBajwa wants to merge 2 commits into
Adyen:mainfrom
TabishRiazBajwa:fix/ienum-gethashcode-case-insensitive

Conversation

@TabishRiazBajwa

Copy link
Copy Markdown

Fixes #1679

GetHashCode() in both modelEnum.mustache and modelInnerEnum.mustache used the default case-sensitive string hash, while Equals() and == use StringComparison.OrdinalIgnoreCase. This violates the .NET hash/equality contract, objects that compare equal must produce equal hash codes.

Description
GetHashCode() was returning Value?.GetHashCode() ?? 0, which is case-sensitive. Since Equals() uses StringComparison.OrdinalIgnoreCase, two instances with the same value but different casing (e.g. "valid" vs "VALID") would be considered equal but produce different hash codes — causing silent lookup failures when used as dictionary keys or in hash sets.

Fixed by replacing with StringComparer.OrdinalIgnoreCase.GetHashCode(Value ?? string.Empty) in both templates.

Tested scenarios

  • Same value with different casing produces equal hash codes
  • Dictionary lookup succeeds when key casing differs from inserted key
  • All existing IEnum tests continue to pass

Fixed issue: #1679

Fixes Adyen#1679

`GetHashCode()` in both `modelEnum.mustache` and `modelInnerEnum.mustache` used the default case-sensitive string hash, while `Equals()` and `==` use `StringComparison.OrdinalIgnoreCase`. This violates the .NET hash/equality contract — objects that compare equal must produce equal hash codes.

**Fix:** Replace `Value?.GetHashCode() ?? 0` with `StringComparer.OrdinalIgnoreCase.GetHashCode(Value ?? string.Empty)` in both templates.

**Tests added:** Two new tests in `IEnumTest` cover the contract — one asserting equal hash codes for same-value-different-case instances, and one proving Dictionary lookup works correctly after the fix.
@TabishRiazBajwa TabishRiazBajwa requested a review from a team as a code owner June 24, 2026 17:42

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the GetHashCode implementation for custom string-based enums in C# templates and tests to use StringComparer.OrdinalIgnoreCase.GetHashCode. This ensures that case-insensitive equality matches the hash code contract, allowing the enums to be used correctly as dictionary keys. Additionally, unit tests were added to verify this behavior. The review feedback correctly points out that using Value ?? string.Empty inside StringComparer.OrdinalIgnoreCase.GetHashCode can lead to hash collisions between null and empty strings (which are treated as unequal by Equals). It is recommended to check if Value is null first to avoid this issue.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread Adyen.Test/Core/IEnumTest.cs Outdated
Comment thread templates-v7/csharp/libraries/generichost/modelEnum.mustache Outdated
Comment thread templates-v7/csharp/libraries/generichost/modelInnerEnum.mustache Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] IEnum GetHashCode is case-sensitive while Equals is case-insensitive, violating hash/equality contract

1 participant