Spinning out of #306. Captures @bartelink's counter-proposal verbatim — the intent of #306 was a TryCreate returning Result<_, exn>, but the deeper observation is that the constructor / Create running structure validation eagerly is the wrong shape, and a TryCreate wrapper becomes obsolete-on-arrival once that is fixed.
Proposal
Create never throws. No structure check at construction time.
- Lazy, cached structure check on first
Parse. Any parse entry point runs the check once (memoised on the parser instance) before doing input parsing. Programmer errors (structure) and user errors (input) end up on the same code path the user is already prepared to handle.
- Opt-out escape hatch.
Create(skipCheckStructure=true) for guaranteed non-throwing construction. XML doc spells out the contract: caller must have run ArgumentParser<T>.CheckStructure() in a test for that schema, otherwise behaviour is undefined.
- Exception taxonomy stays:
ArguException for structure failures (programmer error, raised by the lazy check unless skipCheckStructure=true).
ArguParseException for input failures (user error, raised by parsing).
- Tutorial + samples updated to make the distinction explicit, including the recommended host pattern (
try/with only around Parse*, not around Create).
Why now
Out of scope (follow-up)
Refs #306, #325.
Spinning out of #306. Captures @bartelink's counter-proposal verbatim — the intent of #306 was a
TryCreatereturningResult<_, exn>, but the deeper observation is that the constructor /Createrunning structure validation eagerly is the wrong shape, and aTryCreatewrapper becomes obsolete-on-arrival once that is fixed.Proposal
Createnever throws. No structure check at construction time.Parse. Any parse entry point runs the check once (memoised on the parser instance) before doing input parsing. Programmer errors (structure) and user errors (input) end up on the same code path the user is already prepared to handle.Create(skipCheckStructure=true)for guaranteed non-throwing construction. XML doc spells out the contract: caller must have runArgumentParser<T>.CheckStructure()in a test for that schema, otherwise behaviour is undefined.ArguExceptionfor structure failures (programmer error, raised by the lazy check unlessskipCheckStructure=true).ArguParseExceptionfor input failures (user error, raised by parsing).try/withonly aroundParse*, not aroundCreate).Why now
master(see V7: Extract System.Configuration.ConfigurationManager support into its own package #325 / Extract Argu.Extensions.ConfigurationManager #234) so the breaking change cost is partially amortised.Result-shaped path can land as a follow-up after this — it becomes trivial onceCreateitself can't throw.Out of scope (follow-up)
TryCreate/ResultAPI (revisit after this lands).Refs #306, #325.