Fix parsing inconsistencies between Uri ctors and TryCreate factories#123932
Fix parsing inconsistencies between Uri ctors and TryCreate factories#123932MihaZupan wants to merge 6 commits intodotnet:mainfrom
Conversation
|
Tagging subscribers to this area: @karelz, @dotnet/ncl |
There was a problem hiding this comment.
Pull request overview
Aligns Uri constructors and Uri.TryCreate factory methods by removing duplicated initialization logic and ensuring consistent IRI normalization behavior when falling back to relative URIs.
Changes:
- Refactors URI initialization so constructors and
TryCreateshare a single core creation path (TryCreateThis). - Ensures fallback-to-relative paths apply consistent IRI normalization.
- Expands
ToStringfunctional test data and adds paired coverage for ctor vsTryCreate.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/libraries/System.Private.Uri/src/System/UriExt.cs | Refactors shared URI construction logic to unify ctor and TryCreate behavior and normalize relative-fallback handling. |
| src/libraries/System.Private.Uri/tests/FunctionalTests/UriTests.cs | Adds/extends ToString test cases and mirrors them through TryCreate to validate consistency. |
🤖 Copilot Code Review — PR #123932Holistic AssessmentMotivation: The PR addresses a real inconsistency where Approach: The approach is sound — unify the code paths by introducing a shared Summary: ✅ LGTM. The refactoring is clean, correct, and well-tested. The code eliminates duplication while ensuring behavioral consistency between constructors and Detailed Findings✅ Code Unification — Correctly implementedThe refactoring successfully unifies the constructor and
This eliminates the previous inconsistency where some fallback paths (like implicit file paths or simple syntax errors) did not apply IRI normalization. ✅ Parameterless Constructor — Appropriately scopedThe new
This prevents misuse while enabling the unified code path. ✅ Debug.Assert in CreateHelper — CorrectThe assertion at line 650: Debug.Assert(result.Syntax is { IsSimple: false }, "A custom UriParser threw on InitializeAndValidate.");This correctly asserts that built-in simple parsers should never throw ✅ Test Coverage — AdequateThe test expansion in
✅ Thread Safety — No concernsThe code is thread-safe:
✅ Breaking Change — Appropriately documentedThe PR is correctly labeled with 💡 Suggestion — Minor typo fix already includedCommit 5 (1f7e6d1) fixes "constructos" → "constructors" in the XML doc comment at line 16. Good attention to detail. Models consulted: Claude Sonnet 4, Gemini 3 Pro (GPT-5.1-Codex timed out after 10 minutes) |
This is the "future change" I was referring to in #122001 and #122002.
Urictors andTryCreatefactories used almost the same logic, but the duplication introduced a slight difference in how the fallback to relative Uris was handled.When using
TryCreate, we would skip the iri normalization. E.g. compare01abba3 avoids the code duplication and makes the behavior between the two the same.
The other inconsistency was around how the fallback to relative Uris worked for various cases where we decide we can't create an Absolute one.
If we were falling back from an implicit file path, or an invalid absolute Uri with a valid scheme, we would skip iri normalization.
d50ad4f uses the same logic for all such cases.
The distinction doesn't matter much in practice if you end up combining the Uri with a base, they'll get normalized the same. We could also choose to make the break in the other direction if we wanted to - not do iri normalization for relative uris at all.
It only matters if you interrogate the relative Uri directly. Marking as breaking-change regardless so that we remember to call it out in docs.