Skip to content

feat(#119): Add support for all currently supported .NET frameworks (net9.0, net10.0)#150

Merged
LeeCampbell merged 9 commits intoHdrHistogram:mainfrom
leecampbell-codeagent:agent/119-add-support-for-all-currently-supported-
Mar 4, 2026
Merged

feat(#119): Add support for all currently supported .NET frameworks (net9.0, net10.0)#150
LeeCampbell merged 9 commits intoHdrHistogram:mainfrom
leecampbell-codeagent:agent/119-add-support-for-all-currently-supported-

Conversation

@leecampbell-codeagent
Copy link
Collaborator

Brief: Issue #119 — Add support for all currently supported .NET frameworks (net9.0, net10.0)

Summary

The library currently targets net8.0;netstandard2.0.
As of March 2026, .NET 9 (STS) and .NET 10 (LTS) are both in active support alongside .NET 8 (LTS).
This issue adds net9.0 and net10.0 as target frameworks across the library, test, examples, benchmarking, and CI projects.
No code logic changes are expected — the existing #if NET5_0_OR_GREATER guard in Bitwise.cs already covers all three modern targets.
The spec file spec/tech-standards/build-system.md must also be updated to reflect the new targets.

Affected Files (confirmed by exploration)

File Current value Required value
HdrHistogram/HdrHistogram.csproj net8.0;netstandard2.0 net10.0;net9.0;net8.0;netstandard2.0
HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj net8.0 net10.0;net9.0;net8.0
HdrHistogram.Examples/HdrHistogram.Examples.csproj net8.0 net10.0
HdrHistogram.Benchmarking/HdrHistogram.Benchmarking.csproj net8.0 net10.0;net9.0;net8.0
.github/workflows/ci.yml dotnet-version: 8.0.x 8.0.x, 9.0.x, 10.0.x (multi-line — see CI section below)
.devcontainer/Dockerfile sdk:9.0-bookworm-slim + 8.0 runtime sdk:10.0-bookworm-slim + explicit 8.0 and 9.0 runtimes
spec/tech-standards/build-system.md Documents net8.0;netstandard2.0 Update five specific sections (see Spec Update section below)

Conditional Compilation

Only one #if guard exists in the main library:

  • HdrHistogram/Utilities/Bitwise.cs: #if NET5_0_OR_GREATER — uses System.Numerics.BitOperations.LeadingZeroCount().

This guard already applies correctly to net8.0, net9.0, and net10.0.
No new #if directives are required.
No #if NET9_0_OR_GREATER or #if NET10_0_OR_GREATER optimisations have been identified as necessary for this changeset.

CI YAML Change

The actions/setup-dotnet@v4 action supports a multi-line scalar for dotnet-version.
Use the following exact syntax in .github/workflows/ci.yml:

- uses: actions/setup-dotnet@v4
  with:
    dotnet-version: |
      8.0.x
      9.0.x
      10.0.x
    cache: true
    cache-dependency-path: '**/*.csproj'

Do not use separate setup-dotnet steps for each version — this would break cache: true behaviour.

Devcontainer Change

The current .devcontainer/Dockerfile is based on mcr.microsoft.com/dotnet/sdk:9.0-bookworm-slim and installs only the .NET 8.0 runtime.
The Examples project is a developer-facing runnable tool; after changing its target to net10.0, it must remain buildable inside the devcontainer.

Resolution (Option A): Change the base image to mcr.microsoft.com/dotnet/sdk:10.0-bookworm-slim and add explicit installation of the 8.0 and 9.0 runtimes using the dotnet-install.sh script, so all three runtime versions remain available locally.

Spec Update: Sections to Change in spec/tech-standards/build-system.md

The following five locations must be updated; all other sections (including the AppVeyor section, lines 137–177, which is already acknowledged as outdated) are out of scope:

Approx. Line Section Change
24–26 Main Library TargetFrameworks net8.0;netstandard2.0net10.0;net9.0;net8.0;netstandard2.0
35–37 Test Project TargetFramework net8.0net10.0;net9.0;net8.0
42–45 Benchmarking Project TargetFrameworks net8.0net10.0;net9.0;net8.0
226–228 Benchmark Configuration list "net8.0 (current LTS runtime)" → list all three runtimes
254 Prerequisites ".NET 8.0 SDK (or later)" → ".NET 10.0 SDK (or later)"

The Examples project section is absent from the spec, so no spec change is needed for that project.

Acceptance Criteria

  • HdrHistogram.csproj targets net10.0;net9.0;net8.0;netstandard2.0
  • HdrHistogram.UnitTests.csproj targets net10.0;net9.0;net8.0
  • HdrHistogram.Examples.csproj targets net10.0
  • HdrHistogram.Benchmarking.csproj targets net10.0;net9.0;net8.0
  • CI installs .NET SDK 8.0.x, 9.0.x, and 10.0.x using a single setup-dotnet step with a multi-line dotnet-version scalar
  • .devcontainer/Dockerfile uses sdk:10.0-bookworm-slim base image with 8.0 and 9.0 runtimes installed
  • dotnet build -c Release succeeds for all target frameworks
  • dotnet test passes on all three modern runtimes (net8.0, net9.0, net10.0)
  • dotnet pack produces a NuGet package containing assemblies for all four targets
  • No regressions — all existing tests pass on all targets
  • spec/tech-standards/build-system.md updated at the five specific locations listed above

Test Strategy

No new tests need to be written.
The existing test suite in HdrHistogram.UnitTests/ provides full coverage.
Multi-targeting the test project is sufficient: dotnet test automatically runs all tests against each <TargetFrameworks> entry.
The CI pipeline, once updated to install all three SDKs, will exercise net8.0, net9.0, and net10.0 in a single dotnet test invocation.

Verification locally:

dotnet build HdrHistogram/HdrHistogram.csproj -c Release
dotnet test HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj -c Release
dotnet pack HdrHistogram/HdrHistogram.csproj -c Release --no-build

After dotnet pack, confirm the .nupkg contains lib/net8.0/, lib/net9.0/, lib/net10.0/, and lib/netstandard2.0/ folders.

Risks and Open Questions

  • BenchmarkDotNet compatibility: BenchmarkDotNet version 0.13.12 (currently referenced) must support net10.0.
    Verify during implementation by attempting a Release build of the benchmarking project.
    If BenchmarkDotNet 0.13.12 fails to build against net10.0, upgrade both BenchmarkDotNet and BenchmarkDotNet.Diagnostics.Windows to the latest stable version as part of this PR and update the version recorded in spec/tech-standards/build-system.md accordingly.

  • Examples project: The issue specifies updating to net10.0 only (single target, not multi-target).
    This is intentional — examples are a developer-facing runnable tool, not a shipped library.
    The devcontainer change (see above) ensures local buildability is preserved.

  • Spec update: spec/tech-standards/build-system.md still documents AppVeyor CI.
    That section was already outdated before this issue.
    Only the five target framework and prerequisite locations listed above need updating here; AppVeyor cleanup is out of scope.

Task breakdown

Task List: Issue #119 — Add support for net9.0 and net10.0

Cross-referenced against every acceptance criterion in plan/ready/brief.md.


1 — Main library: target frameworks

File: HdrHistogram/HdrHistogram.csproj

  • 1.1 Change <TargetFrameworks> on line 4 from net8.0;netstandard2.0 to
    net10.0;net9.0;net8.0;netstandard2.0.
    Verify: the element reads exactly <TargetFrameworks>net10.0;net9.0;net8.0;netstandard2.0</TargetFrameworks>.

  • 1.2 Add two <PropertyGroup> conditions for the Release DocumentationFile,
    mirroring the existing block at lines 24–26.
    Add one block for net9.0 (bin\Release\net9.0\HdrHistogram.xml) and one for
    net10.0 (bin\Release\net10.0\HdrHistogram.xml), immediately after the
    existing net8.0 block.
    Verify: both new blocks are present and follow the same pattern as the net8.0 block.

Covers acceptance criteria: AC-1 (HdrHistogram.csproj targets all four TFMs),
AC-8 (dotnet pack produces assemblies for all four targets).


2 — Unit tests: target frameworks

File: HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj

  • 2.1 Change <TargetFrameworks> on line 4 from net8.0 to
    net10.0;net9.0;net8.0.
    Verify: the element reads exactly <TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>.

Covers acceptance criteria: AC-2, AC-7 (dotnet test on all three runtimes),
AC-9 (no regressions).


3 — Examples project: target framework

File: HdrHistogram.Examples/HdrHistogram.Examples.csproj

  • 3.1 Change <TargetFrameworks> on line 5 from net8.0 to net10.0.
    Verify: the element reads exactly <TargetFrameworks>net10.0</TargetFrameworks>.

Covers acceptance criterion: AC-3.


4 — Benchmarking project: target frameworks and BenchmarkDotNet compatibility

File: HdrHistogram.Benchmarking/HdrHistogram.Benchmarking.csproj

  • 4.1 Change <TargetFrameworks> on line 5 from net8.0 to
    net10.0;net9.0;net8.0.
    Verify: the element reads exactly <TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>.

  • 4.2 Attempt a Release build of the benchmarking project:

    dotnet build HdrHistogram.Benchmarking/HdrHistogram.Benchmarking.csproj -c Release

    If the build succeeds, this task is done — BenchmarkDotNet 0.13.12 is compatible.
    If the build fails due to BenchmarkDotNet incompatibility with net10.0, proceed to task 4.3.

  • 4.3 (Conditional — only if task 4.2 fails) Upgrade both
    BenchmarkDotNet and BenchmarkDotNet.Diagnostics.Windows to the latest
    stable version.
    Verify: dotnet build HdrHistogram.Benchmarking/HdrHistogram.Benchmarking.csproj -c Release
    succeeds after the upgrade.
    Note: if this task is executed, also complete task 10.6 in the spec section below.

Covers acceptance criteria: AC-4, AC-6 (dotnet build succeeds for all TFMs).


5 — CI pipeline: multi-version SDK install

File: .github/workflows/ci.yml

  • 5.1 Replace the setup-dotnet step (lines 15–19) with a single step using
    a multi-line dotnet-version scalar:
    - uses: actions/setup-dotnet@v4
      with:
        dotnet-version: |
          8.0.x
          9.0.x
          10.0.x
        cache: true
        cache-dependency-path: '**/*.csproj'
    Do not use separate setup-dotnet steps — that would break cache: true.
    Verify: the file contains exactly one setup-dotnet step, and dotnet-version
    is a multi-line block scalar listing all three versions.

Covers acceptance criterion: AC-5.


6 — Devcontainer: upgrade base image and install additional runtimes

File: .devcontainer/Dockerfile

  • 6.1 Change the FROM line (line 5) from
    mcr.microsoft.com/dotnet/sdk:9.0-bookworm-slim to
    mcr.microsoft.com/dotnet/sdk:10.0-bookworm-slim.
    Verify: the first FROM line references sdk:10.0-bookworm-slim.

  • 6.2 Replace the single 8.0 runtime install (lines 6–8) with explicit
    installs of both the 8.0 and 9.0 runtimes via dotnet-install.sh, keeping both
    in the same RUN layer to avoid creating extra image layers:

    RUN dotnet_version=8.0 \
        && curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin \
           --runtime dotnet --channel $dotnet_version --install-dir /usr/share/dotnet \
        && dotnet_version=9.0 \
        && curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin \
           --runtime dotnet --channel $dotnet_version --install-dir /usr/share/dotnet

    Verify: the file installs both 8.0 and 9.0 runtimes, and the base image is 10.0.

Covers acceptance criterion: AC-6 (devcontainer uses sdk:10.0-bookworm-slim
with 8.0 and 9.0 runtimes installed).


7 — Spec: main library TargetFrameworks

File: spec/tech-standards/build-system.md, approx. lines 24–26

  • 7.1 In the "Main Library (HdrHistogram.csproj)" section, update the XML
    code block from:
    <TargetFrameworks>net8.0;netstandard2.0</TargetFrameworks>
    to:
    <TargetFrameworks>net10.0;net9.0;net8.0;netstandard2.0</TargetFrameworks>
    Verify: the code block in that section reflects all four targets in the correct order.

Covers acceptance criterion: AC-10 (spec updated at specified locations).


8 — Spec: test project TargetFramework

File: spec/tech-standards/build-system.md, approx. lines 35–37

  • 8.1 In the "Test Project" section, update the XML code block from:
    <TargetFramework>net8.0</TargetFramework>
    to:
    <TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>
    Note: the element name changes from the singular TargetFramework to the plural
    TargetFrameworks to match a multi-target declaration.
    Verify: the code block in that section shows all three targets.

Covers acceptance criterion: AC-10.


9 — Spec: benchmarking project TargetFrameworks

File: spec/tech-standards/build-system.md, approx. lines 42–45

  • 9.1 In the "Benchmarking Project" section, update the description text
    "Targets the current LTS runtime only (developer tool, not a shipped library):" to
    reflect multi-targeting, and update the XML code block from:
    <TargetFrameworks>net8.0</TargetFrameworks>
    to:
    <TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>
    Verify: both the description and the code block are updated.

Covers acceptance criterion: AC-10.


10 — Spec: benchmark configuration runtime list

File: spec/tech-standards/build-system.md, approx. lines 226–228

  • 10.1 In the "Benchmark Configuration" section, replace the single target entry:

    - `net8.0` (current LTS runtime)
    

    with a list of all three supported runtimes:

    - `net10.0` (current LTS runtime)
    - `net9.0` (STS runtime)
    - `net8.0` (LTS runtime)
    

    Verify: the bullet list covers all three TFMs.

  • 10.2 (Conditional — only if task 4.3 was executed) Update the BenchmarkDotNet
    version numbers in the "Benchmarking Project" dependencies code block
    (approx. lines 66–67) to match the upgraded version.
    Verify: the version string in the spec matches the version in
    HdrHistogram.Benchmarking/HdrHistogram.Benchmarking.csproj.

Covers acceptance criterion: AC-10.


11 — Spec: prerequisites

File: spec/tech-standards/build-system.md, approx. line 254

  • 11.1 In the "Prerequisites" section, change:
    - .NET 8.0 SDK (or later)
    
    to:
    - .NET 10.0 SDK (or later)
    
    Verify: the prerequisites list references .NET 10.0 SDK.

Covers acceptance criterion: AC-10.


12 — Verification: build, test, and pack

These tasks confirm all acceptance criteria related to running the toolchain.
They must be performed after all implementation tasks above are complete.

  • 12.1 Run a Release build of the main library and confirm it succeeds for
    all four target frameworks:

    dotnet build HdrHistogram/HdrHistogram.csproj -c Release

    Verify: build output shows net10.0, net9.0, net8.0, and netstandard2.0
    all built without errors.

  • 12.2 Run the full test suite and confirm all tests pass on all three
    modern runtimes:

    dotnet test HdrHistogram.UnitTests/HdrHistogram.UnitTests.csproj -c Release

    Verify: test results show three separate net10.0, net9.0, and net8.0 runs,
    all green with zero failures.

  • 12.3 Pack the library and confirm all four TFM folders are present in
    the produced .nupkg:

    dotnet pack HdrHistogram/HdrHistogram.csproj -c Release --no-build

    Then inspect the package:

    unzip -l HdrHistogram/bin/Release/HdrHistogram.*.nupkg | grep "^.*lib/"

    Verify: the archive contains lib/net8.0/, lib/net9.0/, lib/net10.0/,
    and lib/netstandard2.0/ folders.

Covers acceptance criteria: AC-6 (build succeeds), AC-7 (tests pass on
all runtimes), AC-8 (pack contains all four targets), AC-9 (no regressions).



13 — Code review fixes

Issues found during post-implementation review and resolved.

  • 13.1 BenchmarkDotNet version regression: the branch base had 0.13.12 but
    upstream/main already upgraded to 0.15.8.
    Updated HdrHistogram.Benchmarking/HdrHistogram.Benchmarking.csproj to 0.15.8.
    Verified: dotnet build -c Release -p:TargetFrameworks=net9.0 succeeds.

  • 13.2 spec/tech-standards/build-system.md BenchmarkDotNet version block
    also reflected the old 0.13.12.
    Updated both package references in the spec to 0.15.8 to match the csproj.

  • 13.3 spec/tech-standards/build-system.md TFM description table in the
    "Main Library" section was missing rows for net9.0 and net10.0.
    Added net10.0 (current LTS target), net9.0 (STS target), and net8.0 (LTS target) rows.


Acceptance Criterion Cross-Reference

Criterion Tasks
AC-1: HdrHistogram.csproj targets net10.0;net9.0;net8.0;netstandard2.0 1.1
AC-2: HdrHistogram.UnitTests.csproj targets net10.0;net9.0;net8.0 2.1
AC-3: HdrHistogram.Examples.csproj targets net10.0 3.1
AC-4: HdrHistogram.Benchmarking.csproj targets net10.0;net9.0;net8.0 4.1
AC-5: CI installs SDKs 8.0.x, 9.0.x, 10.0.x via single setup-dotnet step 5.1
AC-6: .devcontainer/Dockerfile uses sdk:10.0-bookworm-slim + 8.0 and 9.0 runtimes 6.1, 6.2
AC-6b: dotnet build -c Release succeeds for all TFMs 4.2, 12.1
AC-7: dotnet test passes on net8.0, net9.0, net10.0 12.2
AC-8: dotnet pack produces .nupkg with all four target folders 1.2, 12.3
AC-9: No regressions — all existing tests pass on all targets 12.2
AC-10: spec/tech-standards/build-system.md updated at all five locations 7.1, 8.1, 9.1, 10.1, 11.1

Closes #119

@leecampbell-codeagent
Copy link
Collaborator Author

⚠️ Workflow file changes require manual application

The agent's PAT lacks the workflow scope needed to push changes under .github/workflows/.
Please apply the following diff manually:

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 79a2410..25eda9e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -14,7 +14,10 @@ jobs:
       - uses: actions/checkout@v4
       - uses: actions/setup-dotnet@v4
         with:
-          dotnet-version: '8.0.x'
+          dotnet-version: |
+            8.0.x
+            9.0.x
+            10.0.x
           cache: true
           cache-dependency-path: '**/*.csproj'
 

LeeCampbell
LeeCampbell previously approved these changes Mar 3, 2026
LeeCampbell added a commit to LeeCampbell/HdrHistogram.NET-1 that referenced this pull request Mar 4, 2026
Update setup-dotnet to install all three supported SDK versions (8.0.x,
9.0.x, 10.0.x) using a multi-line dotnet-version scalar, matching the
new multi-target framework support added in HdrHistogram#150.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve merge conflicts with upstream changes to bring the branch
up to date.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LeeCampbell added a commit to LeeCampbell/HdrHistogram.NET-1 that referenced this pull request Mar 4, 2026
Update setup-dotnet to install all three supported SDK versions (8.0.x,
9.0.x, 10.0.x) using a multi-line dotnet-version scalar, matching the
new multi-target framework support added in HdrHistogram#150.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LeeCampbell
LeeCampbell previously approved these changes Mar 4, 2026
The TaggedLogLineMatcher regex used `.+` (greedy match) in the optional
tag group, which relied on backtracking to correctly parse tags. .NET 10
changed regex engine backtracking behaviour, causing the optional group
to be skipped entirely instead of backtracking to find the tag value.

Replace `Tag=.+` with `Tag=[^,]+` to match only non-comma characters,
avoiding the need for backtracking across comma boundaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LeeCampbell added a commit to LeeCampbell/HdrHistogram.NET-1 that referenced this pull request Mar 4, 2026
Update setup-dotnet to install all three supported SDK versions (8.0.x,
9.0.x, 10.0.x) using a multi-line dotnet-version scalar, matching the
new multi-target framework support added in HdrHistogram#150.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@LeeCampbell LeeCampbell merged commit fe38ad3 into HdrHistogram:main Mar 4, 2026
2 checks passed
LeeCampbell added a commit to LeeCampbell/HdrHistogram.NET-1 that referenced this pull request Mar 4, 2026
Update setup-dotnet to install all three supported SDK versions (8.0.x,
9.0.x, 10.0.x) using a multi-line dotnet-version scalar, matching the
new multi-target framework support added in HdrHistogram#150.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

Add support for all currently supported .NET frameworks (net9.0, net10.0)

2 participants