Skip to content

feat(#161): Drop netstandard2.0 target, support net8.0+ only#164

Open
leecampbell-codeagent wants to merge 7 commits intoHdrHistogram:mainfrom
leecampbell-codeagent:agent/161-drop-netstandard2-0-target-support-net8-
Open

feat(#161): Drop netstandard2.0 target, support net8.0+ only#164
leecampbell-codeagent wants to merge 7 commits intoHdrHistogram:mainfrom
leecampbell-codeagent:agent/161-drop-netstandard2-0-target-support-net8-

Conversation

@leecampbell-codeagent
Copy link
Collaborator

Brief: Issue #161 — Drop netstandard2.0 target, support net8.0+ only

Summary

Remove netstandard2.0 from the main library's <TargetFrameworks>, retaining only net10.0;net9.0;net8.0.
This eliminates all conditional compilation guards that existed solely to support the older target, simplifies Bitwise.cs to use BitOperations.LeadingZeroCount unconditionally, and cleans up a branching code path in HistogramLogReader.cs.
The three per-framework Release PropertyGroup conditions in the csproj are collapsed into a single unconditional PropertyGroup as part of this change.
The spec file build-system.md must be updated to reflect the new target list.

Previous NuGet releases remain available on NuGet.org for consumers on .NET Framework or older runtimes.

Category

chore

This is a maintenance and simplification task.
The hardware-intrinsic LeadingZeroCount path (#if NET5_0_OR_GREATER) is already compiled in for all net8.0+ builds; removing the fallback does not change the compiled output for any net8.0, net9.0, or net10.0 consumer.
No performance improvement is delivered to existing net8.0+ consumers — the change reduces build artefacts, removes dead code, and simplifies the codebase.

Affected Files (confirmed by exploration)

File Change required
HdrHistogram/HdrHistogram.csproj Remove netstandard2.0 from <TargetFrameworks> (line 4); delete the netstandard2.0 PropertyGroup condition (lines 36-39); collapse the three per-framework Release PropertyGroup conditions (lines 24-34) into a single Condition="'$(Configuration)' == 'Release'" block
HdrHistogram/Utilities/Bitwise.cs Remove #if NET5_0_OR_GREATER guards (lines 25-29, 32-44); inline IntrinsicNumberOfLeadingZeros body directly into NumberOfLeadingZeros; delete the entire Bitwise.Imperative class (lines 55-109)
HdrHistogram/HistogramLogReader.cs Remove #if NETSTANDARD2_0 block in IsComment() (lines 241-248); keep the char overload unconditionally
spec/tech-standards/build-system.md Remove netstandard2.0 from the TargetFrameworks code block (line 25) and from the target table (line 33)
HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs Remove the ImperativeImplementation benchmark method (references deleted Bitwise.Imperative class)

No other files in the codebase contain #if NETSTANDARD or #if NET5_0_OR_GREATER blocks.
Unit-test and benchmarking projects already target net10.0;net9.0;net8.0 only — no changes needed there.

Acceptance Criteria

  • Library targets net10.0;net9.0;net8.0 only; netstandard2.0 is absent from HdrHistogram.csproj
  • No #if NETSTANDARD or #if NET5_0_OR_GREATER conditional compilation remains anywhere in the library
  • Bitwise.Imperative class is fully removed
  • Bitwise.NumberOfLeadingZeros calls System.Numerics.BitOperations.LeadingZeroCount unconditionally
  • HistogramLogReader.IsComment uses line.StartsWith('#') (char overload) unconditionally
  • The three per-framework Release PropertyGroup conditions are collapsed into a single Condition="'$(Configuration)' == 'Release'" block
  • LeadingZeroCountBenchmarkBase.cs no longer references Bitwise.Imperative; the benchmarking project compiles cleanly
  • All unit tests pass on net8.0, net9.0, and net10.0
  • spec/tech-standards/build-system.md no longer references netstandard2.0

Test Strategy

Existing tests

No unit tests directly target Bitwise or HistogramLogReader.IsComment in isolation.
The existing suite exercises both paths indirectly via histogram recording and log-reading tests.
Run the full unit-test suite across all three target frameworks after the changes:

dotnet test -c Release

All tests must pass; no new test failures are acceptable.

New tests (optional but recommended)

Consider adding a focused unit test in HdrHistogram.UnitTests/ that asserts Bitwise.NumberOfLeadingZeros returns correct values for a range of inputs (including 0, 1, powers-of-two, and long.MaxValue).
This is low-risk but provides a regression anchor if Bitwise.cs is touched again.

There is no need to add tests for IsComment — it is a private static helper with trivial logic.

Risks and Open Questions

  1. Benchmark class references Bitwise.Imperative — deleting the class will break the ImperativeImplementation benchmark at compile time.
    The benchmark must be updated in the same PR (listed in Affected Files above).

  2. NuGet package surface — removing a target framework is a breaking change for consumers on netstandard2.0.
    This is explicitly accepted: "Previous NuGet releases will remain available."
    The PR description should note this prominently and suggest a major-version bump or release notes entry.

  3. No other conditional compilation found — the grep over the codebase confirmed only two files contain the relevant #if blocks.
    Low risk of missing anything.

Task breakdown

Task List: Issue #161 — Drop netstandard2.0 target, support net8.0+ only

Implementation Changes

  • HdrHistogram/HdrHistogram.csproj line 4 — Remove netstandard2.0 from <TargetFrameworks>, leaving net10.0;net9.0;net8.0.

    • Why: Drops the legacy target entirely.
    • Verify: <TargetFrameworks> value contains no netstandard2.0 token.
  • HdrHistogram/HdrHistogram.csproj lines 24–34 — Collapse the three per-framework Release PropertyGroup blocks (one each for net8.0, net9.0, net10.0) into a single PropertyGroup Condition="'$(Configuration)' == 'Release'" block with a single <DocumentationFile> element that resolves via $(TargetFramework).

    • Why: Eliminates duplicated XML and the framework-specific condition strings.
    • Verify: Only one Release PropertyGroup exists; it contains no $(TargetFramework) literals in the condition string.
  • HdrHistogram/HdrHistogram.csproj lines 36–39 — Delete the netstandard2.0 PropertyGroup block (the one setting DefineConstants to RELEASE;NETSTANDARD2_0).

    • Why: The constant NETSTANDARD2_0 is no longer needed once the target is removed.
    • Verify: No PropertyGroup referencing netstandard2.0 or NETSTANDARD2_0 remains in the file.
  • HdrHistogram/Utilities/Bitwise.cs lines 23–44 — Simplify NumberOfLeadingZeros(long) to call System.Numerics.BitOperations.LeadingZeroCount((ulong)value) directly; remove the #if NET5_0_OR_GREATER / #else / #endif guards and delete the private IntrinsicNumberOfLeadingZeros helper.

    • Why: All supported targets (net8.0+) provide BitOperations.LeadingZeroCount; the conditional dispatch is dead code.
    • Verify: NumberOfLeadingZeros body is a single return System.Numerics.BitOperations.LeadingZeroCount((ulong)value); statement; no #if directives remain in the method or immediately around it.
  • HdrHistogram/Utilities/Bitwise.cs lines 55–109 — Delete the entire Bitwise.Imperative nested public static class (including the Lookup table, NumberOfLeadingZeros, NumberOfLeadingZerosLong, and Log2 methods).

    • Why: The imperative fallback path is unreachable on net8.0+; removing it eliminates dead code and the public surface that the benchmark references.
    • Verify: No class Imperative or Bitwise.Imperative identifier exists anywhere in the solution.
  • HdrHistogram/HistogramLogReader.cs lines 241–248 — Remove the #if NETSTANDARD2_0 / #else / #endif block inside IsComment(string line), keeping only return line.StartsWith('#');.

    • Why: The char overload of StartsWith is available on all net8.0+ targets; the string-overload fallback is dead code.
    • Verify: IsComment contains no #if directives; the method body is return line.StartsWith('#');.
  • HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs — Remove the "Imperative" entry from the validation dictionary (line 56) and delete the ImperativeImplementation() benchmark method (lines 124–133).

    • Why: Both reference Bitwise.Imperative which will no longer exist; leaving them causes a compile error.
    • Verify: dotnet build HdrHistogram.Benchmarking/ -c Release exits with code 0; no reference to Bitwise.Imperative remains in the file.

Unit Tests

  • HdrHistogram.UnitTests/ — Add a focused unit test class BitwiseTests (e.g. HdrHistogram.UnitTests/Utilities/BitwiseTests.cs) that asserts Bitwise.NumberOfLeadingZeros returns correct results for representative inputs: 0, 1, 2, powers of two up to 2⁶², and long.MaxValue.

    • Why: No existing test directly covers Bitwise; this provides a regression anchor if the method is ever touched again.
    • Verify: Test class exists; dotnet test -c Release reports the new tests as passing on all three target frameworks.
  • Run the full unit-test suite — Execute dotnet test -c Release across all three target frameworks (net8.0, net9.0, net10.0).

    • Why: Confirms that removing the netstandard2.0 conditional paths has not broken any indirect consumer of Bitwise or HistogramLogReader.
    • Verify: Zero test failures; zero skipped tests that were previously passing.

Documentation

  • spec/tech-standards/build-system.md line 25 — Remove netstandard2.0 from the <TargetFrameworks> code block example.

    • Why: The spec must reflect the actual supported targets.
    • Verify: The code block contains only net10.0;net9.0;net8.0.
  • spec/tech-standards/build-system.md line 33 — Delete the | \netstandard2.0` | Broad compatibility (.NET Framework 4.6.1+, .NET Core 2.0+) |` row from the target table.

    • Why: The target no longer exists; the row is misleading.
    • Verify: No mention of netstandard2.0 remains anywhere in build-system.md.

Acceptance Criteria Cross-Reference

Acceptance criterion (from brief) Covered by task
Library targets net10.0;net9.0;net8.0 only; netstandard2.0 absent from .csproj Task 1 (TargetFrameworks)
No #if NETSTANDARD or #if NET5_0_OR_GREATER conditional compilation in library Tasks 4, 6 (Bitwise.cs, HistogramLogReader.cs)
Bitwise.Imperative class fully removed Task 5
Bitwise.NumberOfLeadingZeros calls BitOperations.LeadingZeroCount unconditionally Task 4
HistogramLogReader.IsComment uses line.StartsWith('#') unconditionally Task 6
Three per-framework Release PropertyGroup conditions collapsed into one Task 2
LeadingZeroCountBenchmarkBase.cs no longer references Bitwise.Imperative; benchmarking project compiles Task 7
All unit tests pass on net8.0, net9.0, net10.0 Tasks 8 (new tests), 9 (full suite)
spec/tech-standards/build-system.md no longer references netstandard2.0 Tasks 10, 11

Closes #161

@LeeCampbell LeeCampbell force-pushed the agent/161-drop-netstandard2-0-target-support-net8- branch from c8cf9a6 to f97a0dc Compare March 23, 2026 01:47
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.

Drop netstandard2.0 target, support net8.0+ only

1 participant