Skip to content

style: idiomatic cleanups in PhoneNumberUtil platform partials - #417

Merged
twcclegg merged 2 commits into
mainfrom
style/phonenumberutil-platform
Aug 26, 2026
Merged

style: idiomatic cleanups in PhoneNumberUtil platform partials#417
twcclegg merged 2 commits into
mainfrom
style/phonenumberutil-platform

Conversation

@twcclegg

Copy link
Copy Markdown
Owner

Summary

Small idiomatic-C# readability pass over the two platform-specific halves of the PhoneNumberUtil partial class — part of the broader file-by-file cleanup sweep (see #409). Not fixing bugs, not chasing Java parity (these two files are this port's own platform-conditional compilation split, with no single Java equivalent), not restructuring logic.

  • PhoneNumberUtil.net.cs (net8.0/net10.0 half): == null / != nullis null / is not null pattern matching throughout; the leading if (number == null) throw new ArgumentNullException(...) in Format replaced with ArgumentNullException.ThrowIfNull(number), available since this half only ever compiles under NET5_0_OR_GREATER in this repo's actual TFM set (netstandard2.0/net8.0/net10.0).
  • PhoneNumbers/PhoneNumberUtil.netstandard.cs (netstandard2.0 half): same is null/is not null conversions; kept the manual if (number is null) throw ... since ArgumentNullException.ThrowIfNull isn't part of netstandard2.0's API surface.

Verified no operator ==/!= overloads exist on the affected types (PhoneNumber, NumberFormat), so is null/is not null is behavior-identical to the reference-equality ==/!= it replaces.

Test plan

  • dotnet build csharp/PhoneNumbers.slnx — clean build, 0 warnings (TreatWarningsAsErrors), all three TFMs (netstandard2.0, net8.0, net10.0)
  • dotnet test csharp/PhoneNumbers.Test/PhoneNumbers.Test.csproj — 414/414 passing on net8.0 and net10.0

…orm partials

Replace == null / != null with is null / is not null pattern matching
(no operator overloads on the affected types, so behavior is identical),
and use ArgumentNullException.ThrowIfNull in the net8.0/net10.0 half
where the BCL helper is available. The netstandard2.0 half keeps the
manual throw since ThrowIfNull isn't part of that target's API surface.
@codecov

codecov Bot commented Aug 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.90909% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 87.48%. Comparing base (e75ae83) to head (0828279).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
csharp/PhoneNumbers/PhoneNumberUtil.net.cs 90.90% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #417      +/-   ##
==========================================
+ Coverage   87.42%   87.48%   +0.06%     
==========================================
  Files          41       41              
  Lines        3856     3852       -4     
  Branches      990      990              
==========================================
- Hits         3371     3370       -1     
+ Misses        283      281       -2     
+ Partials      202      201       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown

📊 Benchmark Results

Commit: 0828279 · Full run · Linux ubuntu-24.04-arm

Both sides were measured on the same runner in the same job, so the numbers are
comparable. Treat sub-percent differences as noise.

PR branch

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
InputDigitPerKeystroke 1000 4.538 ms 0.0592 ms 0.0525 ms 54.6875 3.88 MB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  Job-AMQORM : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Runtime=.NET 10.0  InvocationCount=1  IterationCount=20  
LaunchCount=1  RunStrategy=ColdStart  UnrollFactor=1  
WarmupCount=1  

Method Mean Error StdDev Allocated
CreateInstance 410.6 μs 103.5 μs 119.2 μs 119.48 KB
CreateInstanceAndLoadAllRegions 7,061.1 μs 369.3 μs 425.3 μs 1620.34 KB
FirstRegionLookup 456.3 μs 156.4 μs 180.1 μs 124.54 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ExtractPossibleNumber_CleanInput 1000 20.92 μs 0.017 μs 0.016 μs - -
ExtractPossibleNumber_WithLeadingJunk 1000 38.44 μs 0.067 μs 0.062 μs 0.6714 48360 B

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
FindNumbers_Valid 100 142.5 μs 0.30 μs 0.26 μs 0.9766 70.71 KB
FindNumbers_StrictGrouping 100 321.4 μs 0.66 μs 0.62 μs 1.4648 124.84 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
GetDescriptionForNumber 1000 1,437.02 μs 2.413 μs 2.139 μs 1.9531 196.59 KB
GetDisplayCountry 1000 18.48 μs 0.017 μs 0.015 μs 0.0916 7.56 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ParseValidateAndFormatPhoneNumbers 1000 2,804.8 μs 53.72 μs 73.53 μs 7.8125 577.71 KB
ParseOnly 1000 433.2 μs 0.46 μs 0.41 μs 4.8828 348.13 KB
ParseNationalFormat 1000 778.5 μs 1.47 μs 1.30 μs 5.8594 431.36 KB
ParseWithExtension 1000 1,114.6 μs 1.59 μs 1.41 μs 13.6719 957.38 KB
ValidateOnly 1000 753.3 μs 1.14 μs 1.01 μs - 41.11 KB
FormatOnly 1000 1,079.8 μs 2.87 μs 2.68 μs 1.9531 187.92 KB
PR base

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
InputDigitPerKeystroke 1000 4.432 ms 0.0504 ms 0.0471 ms 54.6875 3.88 MB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  Job-AMQORM : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Runtime=.NET 10.0  InvocationCount=1  IterationCount=20  
LaunchCount=1  RunStrategy=ColdStart  UnrollFactor=1  
WarmupCount=1  

Method Mean Error StdDev Allocated
CreateInstance 399.9 μs 107.3 μs 123.5 μs 119.48 KB
CreateInstanceAndLoadAllRegions 7,058.3 μs 392.9 μs 452.5 μs 1620.34 KB
FirstRegionLookup 469.2 μs 150.8 μs 173.6 μs 124.54 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ExtractPossibleNumber_CleanInput 1000 21.55 μs 0.024 μs 0.022 μs - -
ExtractPossibleNumber_WithLeadingJunk 1000 38.32 μs 0.059 μs 0.046 μs 0.6714 48360 B

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
FindNumbers_Valid 100 141.9 μs 0.18 μs 0.16 μs 0.9766 70.71 KB
FindNumbers_StrictGrouping 100 321.9 μs 0.67 μs 0.60 μs 1.4648 124.84 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Median Gen0 Allocated
GetDescriptionForNumber 1000 1,417.28 μs 27.141 μs 36.232 μs 1,437.95 μs 1.9531 196.59 KB
GetDisplayCountry 1000 18.49 μs 0.040 μs 0.037 μs 18.50 μs 0.0916 7.56 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ParseValidateAndFormatPhoneNumbers 1000 2,804.1 μs 56.03 μs 153.39 μs 7.8125 577.71 KB
ParseOnly 1000 438.7 μs 0.45 μs 0.40 μs 4.8828 348.13 KB
ParseNationalFormat 1000 783.3 μs 2.07 μs 1.83 μs 5.8594 431.36 KB
ParseWithExtension 1000 1,114.9 μs 2.23 μs 1.98 μs 13.6719 957.38 KB
ValidateOnly 1000 751.4 μs 2.08 μs 1.95 μs - 41.11 KB
FormatOnly 1000 1,092.0 μs 13.41 μs 12.55 μs 1.9531 187.92 KB

…tadata

Upstream Java gates this branch on metadataForRegionCallingFrom != null
before dereferencing it; the C# port had swapped that for
IsValidRegionCode(regionCallingFrom), a different condition that can
diverge from actual metadata resolution (e.g. under a custom
IMetadataLoader with gaps), leaving the dereference on the next line
unguarded. Ported the null check faithfully in both TFM halves
(net.cs and netstandard.cs share the same logic). Flagged by CodeQL
(cs/dereferenced-value-may-be-null, alert #244) on the netstandard.cs
side.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@twcclegg
twcclegg merged commit 67f250d into main Aug 26, 2026
8 checks passed
@twcclegg
twcclegg deleted the style/phonenumberutil-platform branch August 26, 2026 15:07
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.

1 participant