Skip to content

Report a null pair key in ContiguousMap and InsertionOrderMap as "item" or "dictionary" [patch] - #165

Open
matt-edmondson wants to merge 2 commits into
mainfrom
fix/null-pair-key-paramname-164
Open

matt-edmondson wants to merge 2 commits into
mainfrom
fix/null-pair-key-paramname-164

Conversation

@matt-edmondson

@matt-edmondson matt-edmondson commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #164

What was wrong

In ContiguousMap and InsertionOrderMap, a null key passed to Contains(KeyValuePair) or Remove(KeyValuePair), or enumerated by the dictionary passed to an IDictionary constructor, threw ArgumentNullException with ParamName == "key". None of those methods has a parameter called key. The name came from the inner Dictionary.TryGetValue or from the constructors' Add(key, value). OrderedMap already reports "item" and "dictionary" here.

Change

  • New internal PairLookup.Contains(map, item). It checks the key with NullKey.ThrowIfNullItem(item.Key), as OrderedMap does, then compares the value. Contains(KeyValuePair) and Remove(KeyValuePair) in both maps now call it. They were the same code in both maps, and SonarCloud flagged the first version of this PR for 48% duplication on new code.
  • Both IDictionary constructors in both maps call NullKey.ThrowIfNullIn(pair.Key) for each source pair, as OrderedMap.BuildSorted does.
  • The XML docs for the constructors now list the null-key ArgumentNullException.
  • Add(KeyValuePair) still reports "key", as the issue asks. That matches all three maps, OrderedMap included.

Tests

  • NullKeyParamNameTests now covers Contains/Remove(KeyValuePair) for ContiguousMap and InsertionOrderMap. New tests ContiguousMap_DictionaryConstructorWithNullKey_ReportsDictionary and InsertionOrderMap_DictionaryConstructorWithNullKey_ReportsDictionary cover the constructors.
  • Without the library change, all 4 affected tests fail (expected "item"/"dictionary", actual "key").
  • Full suite on Linux / .NET 10: 581/581 passed. The library builds on every target.

🤖 Generated with Claude Code

https://claude.ai/code/session_017vfJW3faRnes8WmPvx9zps

matt-edmondson and others added 2 commits November 13, 2026 03:24
…m" or "dictionary" [patch]

Contains(KeyValuePair) and Remove(KeyValuePair) now check the key with
NullKey.ThrowIfNullItem, and the IDictionary constructors check each
source key with NullKey.ThrowIfNullIn, as OrderedMap already does.
Before, the name "key" leaked from the inner Dictionary or from Add.

Fixes #164

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW3faRnes8WmPvx9zps
Contains(KeyValuePair) and Remove(KeyValuePair) were the same code in
both maps, which SonarCloud flagged as 48% duplication on new code.
They now call one PairLookup.Contains that checks the key with
NullKey.ThrowIfNullItem and compares the value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW3faRnes8WmPvx9zps
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant