Problem
Probes on 6.0.0 (net10.0 and the netstandard2.0 asset consumed from net8) show two null holes:
Dyn.tryGet / Dyn.exists / Dyn.set on a null target throw NullReferenceException. tryGet / exists are the non-throwing lookup APIs; NRE is the wrong answer. A missing member is None / false. A null target should be the same, or a named ArgumentNullException, not NRE.
Dyn.explicitConvert / explicitConvertTo on null throw NRE. implicitConvertTo already has a null shortcut (Dyn.fs: null → return null, then unbox). Explicit does not. null |> implicitConvertTo typeof<string> is null; null |> explicitConvert is NRE.
Present null values are already specified (Some null, exists is true). This ticket is the target (and explicit convert of null), not that case.
What this issue covers
tryGet / exists on a null target: None / false (preferred) or ArgumentNullException. Pick one, test it, document it.
explicitConvert / explicitConvertTo on null: same rule as implicitConvertTo (null in, null out for reference 'T; value 'T still fails), not NRE.
- Tests on net10. Caveats updated to match the new behavior.
Not this issue
- Docs-only recording of today's NRE (separate caveats ticket).
- 15-arg TypeLoadException / ImpromptuInterface (#29).
- C# optional parameters.
- #108.
Acceptance
(null: obj) |> Dyn.tryGet "X" is None (or throws ArgumentNullException if that is the chosen contract). Same idea for exists.
null |> Dyn.explicitConvert as string matches implicitConvertTo typeof<string> (null, not NRE).
- Facts cover the null-target and explicit-null cases.
- Caveats no longer describe NRE as the intended result if behavior changed.
Problem
Probes on 6.0.0 (
net10.0and thenetstandard2.0asset consumed from net8) show two null holes:Dyn.tryGet/Dyn.exists/Dyn.seton a null target throwNullReferenceException.tryGet/existsare the non-throwing lookup APIs; NRE is the wrong answer. A missing member isNone/false. A null target should be the same, or a namedArgumentNullException, not NRE.Dyn.explicitConvert/explicitConvertToon null throw NRE.implicitConvertToalready has a null shortcut (Dyn.fs: null → return null, then unbox). Explicit does not.null |> implicitConvertTo typeof<string>is null;null |> explicitConvertis NRE.Present null values are already specified (
Some null,existsis true). This ticket is the target (and explicit convert of null), not that case.What this issue covers
tryGet/existson a null target:None/false(preferred) orArgumentNullException. Pick one, test it, document it.explicitConvert/explicitConvertToon null: same rule asimplicitConvertTo(null in, null out for reference'T; value'Tstill fails), not NRE.Not this issue
Acceptance
(null: obj) |> Dyn.tryGet "X"isNone(or throwsArgumentNullExceptionif that is the chosen contract). Same idea forexists.null |> Dyn.explicitConvertasstringmatchesimplicitConvertTo typeof<string>(null, not NRE).