Skip to content

Nullable Reference Types - #642

Merged
rexm merged 2 commits into
Handlebars-Net:masterfrom
TheConstructor:feature/nullable-references
Aug 5, 2026
Merged

Nullable Reference Types#642
rexm merged 2 commits into
Handlebars-Net:masterfrom
TheConstructor:feature/nullable-references

Conversation

@TheConstructor

Copy link
Copy Markdown
Contributor

I tried my best to annotate everything with Nullable Reference Annotations, and to convince the compiler of them (i.e. move assignments to the expected positions, ...). It's definitely a big PR. Sorry.

@rexm

rexm commented Jun 23, 2026

Copy link
Copy Markdown
Member

What is the purpose?

@TheConstructor

TheConstructor commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

What is the purpose?

It may make it more obvious to the user of the library when Handlebars.Net expect something not to be null on one hand, and it will make the compiler push you to make null-checks at the right times - at least in theory. There are some situations, were the tooling isn't advanced enough to understand when something can or can't be null. Still it usually leads to fewer unthought of NullReferenceExceptions.

If you are new to NRT you might read https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/attributes/nullable-analysis - it contains some use-cases and how describes how the tooling tries to help you

@TheConstructor
TheConstructor force-pushed the feature/nullable-references branch from 0acc55b to 2a6fdd7 Compare June 24, 2026 21:17
@rexm
rexm merged commit 5015116 into Handlebars-Net:master Aug 5, 2026
6 checks passed
rexm added a commit that referenced this pull request Aug 6, 2026
…te-type Try-methods

PR #642 annotated all Try* out-parameters with [MaybeNullWhen(false)] on a
non-nullable T, which is the correct pattern for unconstrained generic type
parameters (as in Dictionary<TKey,TValue>.TryGetValue) but not for concrete
reference types. For concrete types, the BCL convention (e.g. Uri.TryCreate)
is [NotNullWhen(true)] out T? - this also gives callers a compiler warning
if they dereference the out value without checking the return value first,
which MaybeNullWhen(false) on non-nullable T silently allows.

Updates IHelperResolver, IObjectDescriptorProvider (and implementers),
IFormatterProvider (and implementers), TypeExtensions.IsAssignableToGenericType,
and BlockAccumulatorContext.IsDetachedClosingElement. Generic-TValue Try-methods
(LookupSlim, DictionarySlim, FixedSizeDictionary, CascadeIndex, ObservableIndex)
are left as-is since they correctly mirror the BCL generic pattern.

Fixes #654
rexm added a commit that referenced this pull request Aug 6, 2026
…es PR

PR #642 touched two public readonly array field declarations (adding `?`
annotations) without changing their design, which caused SonarCloud to
flag S3887 ("non-private readonly field exposes mutable array") as new
Bug-type issues on both lines, dropping the reliability rating from A to B.

- Closure.A: made internal, since Closure's constructor is already
  internal and the field is unreachable by external consumers. Added
  InternalsVisibleTo("Handlebars.Test") for the one test that reads it
  directly, and pass BindingFlags.NonPublic to the reflection GetField
  call that resolves this field for compiled closure expressions.
- PathInfo.Segments: left public with a NOSONAR suppression instead,
  since PathInfo instances do reach public surfaces (HelperOptions,
  PathExpression, etc.) and the field has been public since 2020 -
  flipping it to internal would be a real breaking change.
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.

2 participants