Skip to content

Add netstandard2.0 target for .NET Framework 4.6.2+ support#162

Merged
haacked merged 3 commits intomainfrom
haacked/netstandard2.0
Feb 27, 2026
Merged

Add netstandard2.0 target for .NET Framework 4.6.2+ support#162
haacked merged 3 commits intomainfrom
haacked/netstandard2.0

Conversation

@haacked
Copy link
Collaborator

@haacked haacked commented Feb 26, 2026

Summary

  • Adds netstandard2.0 as a target framework alongside netstandard2.1 and net8.0, enabling the SDK on .NET Framework 4.6.2+ projects
  • Uses hand-written polyfills consistent with the existing codebase approach (no Meziantou.Polyfill or other external source generators)
  • Adds Microsoft.Bcl.HashCode as a conditional ns2.0-only dependency

Picks up the work from #147 (author stopped responding) with a different approach — extending the existing polyfill infrastructure instead of introducing an external polyfill package.

Polyfills added (#if NETSTANDARD2_0 only)

  • System.Index / System.Range — enables C# 8 index/range syntax (^1, ..)
  • string.Contains(string, StringComparison), string.Replace(string, string?, StringComparison), string.GetHashCode(StringComparison)
  • Dictionary<K,V>.TryAdd, IReadOnlyDictionary<K,V>.GetValueOrDefault, KeyValuePair<K,V>.Deconstruct

Other changes

  • Default interface implementations in IFeatureFlagCache guarded with #if !NETSTANDARD2_0 (ns2.0 lacks CLR support for DIM). All known implementors already provide explicit implementations.
  • Dictionary(IReadOnlyDictionary) constructor calls replaced with ToDictionary() for ns2.0 compatibility
  • Minor nullable annotation fixes for APIs that lack [DoesNotReturnIf]/[NotNullWhen] on ns2.0

Closes #145

Test plan

  • dotnet build succeeds for all three targets (ns2.0, ns2.1, net8.0) with 0 warnings
  • dotnet test — all existing tests pass
  • dotnet pack — NuGet package contains all three TFM folders
  • Microsoft.Bcl.HashCode only appears as a dependency for ns2.0 consumers
  • CI passes

Add netstandard2.0 as a target framework alongside netstandard2.1 and
net8.0 using hand-written polyfills (no external polyfill packages).

Key changes:
- Add netstandard2.0 to PostHog.csproj and TestLibrary.csproj targets
- Add Microsoft.Bcl.HashCode as a conditional ns2.0-only dependency
- Guard default interface implementations in IFeatureFlagCache with
  #if !NETSTANDARD2_0 (ns2.0 lacks CLR support for DIM)
- Replace Dictionary(IReadOnlyDictionary) constructor calls with
  ToDictionary() for ns2.0 compatibility
- Add polyfills for System.Index, System.Range, string.Contains,
  string.Replace, string.GetHashCode, Dictionary.TryAdd,
  IReadOnlyDictionary.GetValueOrDefault, and KeyValuePair.Deconstruct

Closes #145
@haacked haacked requested a review from Copilot February 26, 2026 19:44
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

11 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@github-actions
Copy link
Contributor

github-actions bot commented Feb 26, 2026

posthog-dotnet Compliance Report

Date: 2026-02-26 23:15:20 UTC
Duration: 120019ms

✅ All Tests Passed!

29/29 tests passed


Capture Tests

29/29 tests passed

View Details
Test Status Duration
Format Validation.Event Has Required Fields 151ms
Format Validation.Event Has Uuid 126ms
Format Validation.Event Has Lib Properties 111ms
Format Validation.Distinct Id Is String 111ms
Format Validation.Token Is Present 115ms
Format Validation.Custom Properties Preserved 114ms
Format Validation.Event Has Timestamp 111ms
Retry Behavior.Retries On 503 8123ms
Retry Behavior.Does Not Retry On 400 2020ms
Retry Behavior.Does Not Retry On 401 2013ms
Retry Behavior.Respects Retry After Header 8119ms
Retry Behavior.Implements Backoff 22135ms
Retry Behavior.Retries On 500 6118ms
Retry Behavior.Retries On 502 6119ms
Retry Behavior.Retries On 504 6119ms
Retry Behavior.Max Retries Respected 22035ms
Deduplication.Generates Unique Uuids 117ms
Deduplication.Preserves Uuid On Retry 6114ms
Deduplication.Preserves Uuid And Timestamp On Retry 13126ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry 6125ms
Deduplication.No Duplicate Events In Batch 117ms
Deduplication.Different Events Have Different Uuids 112ms
Compression.Sends Gzip When Enabled 110ms
Batch Format.Uses Proper Batch Structure 110ms
Batch Format.Flush With No Events Sends Nothing 106ms
Batch Format.Multiple Events Batched Together 116ms
Error Handling.Does Not Retry On 403 2010ms
Error Handling.Does Not Retry On 413 2013ms
Error Handling.Retries On 408 6118ms

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds netstandard2.0 support to the SDK so it can be consumed by .NET Framework 4.6.2+ projects, using in-repo polyfills and conditional dependencies to keep behavior consistent across TFMs.

Changes:

  • Add netstandard2.0 to the target frameworks for the main library and TestLibrary.
  • Introduce NETSTANDARD2_0-only polyfills for missing BCL APIs (Index/Range, string overloads, dictionary helpers).
  • Guard default interface implementations and adjust a few call sites for netstandard2.0 compatibility; add Microsoft.Bcl.HashCode only for netstandard2.0.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/TestLibrary/TestLibrary.csproj Adds netstandard2.0 target and adjusts conditional package reference.
tests/TestLibrary/Fakes/Polyfills/StringPolyfills.cs Adds a small NETSTANDARD2_0 string polyfill used by tests.
tests/TestLibrary/Fakes/FakeLoggerProvider.cs Replaces dictionary construction to be compatible with older TFMs.
tests/TestLibrary/Fakes/FakeHttpMessageHandler.cs Minor nullability/operator adjustments in request capture logic.
src/PostHog/PostHog.csproj Adds netstandard2.0 target and a conditional Microsoft.Bcl.HashCode dependency.
src/PostHog/Library/Polyfills/StringPolyfills.cs Adds NETSTANDARD2_0 polyfills for missing string overloads.
src/PostHog/Library/Polyfills/IndexRangePolyfill.cs Adds System.Index/System.Range polyfills for C# indices/ranges on netstandard2.0.
src/PostHog/Library/Polyfills/DictionaryPolyfills.cs Adds NETSTANDARD2_0 polyfills for TryAdd, GetValueOrDefault, and Deconstruct.
src/PostHog/Features/IFeatureFlagCache.cs Guards default interface implementations to avoid DIM on netstandard2.0.
src/PostHog/Features/Group.cs Adjusts dictionary copy to be compatible with netstandard2.0.
src/PostHog/ErrorTracking/ExceptionPropertiesBuilder.cs Nullability adjustment for netstandard2.0 annotation gaps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Guard against empty oldValue in StringPolyfills.Replace to prevent
infinite loop, add clarifying comments for null-forgiving operators
in FakeHttpMessageHandler and the DIM conditional compilation pattern
in IFeatureFlagCache.
In Release builds, JIT optimizations strip source file paths from
async state machine stack frames, causing assertions on filename and
context_line to fail. Guard these assertions on whether source info
is actually present, and skip the IO-lock test when no source path
is available.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@haacked haacked requested a review from a team February 26, 2026 23:32
Copy link

@jordanm-posthog jordanm-posthog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

@haacked haacked merged commit f3a8bb6 into main Feb 27, 2026
16 checks passed
@haacked haacked deleted the haacked/netstandard2.0 branch February 27, 2026 03:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add target for netstandard2.0

3 participants