Skip to content

Add net35/net10.0 targets with compiler guards for APIs unsupported by PolyShim#17

Merged
Tyrrrz merged 14 commits intoprimefrom
copilot/add-compiler-guards-for-powerkit
Apr 14, 2026
Merged

Add net35/net10.0 targets with compiler guards for APIs unsupported by PolyShim#17
Tyrrrz merged 14 commits intoprimefrom
copilot/add-compiler-guards-for-powerkit

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 13, 2026

PowerKit needs to compile on .NET Framework 3.5 with PolyShim. PolyShim 2.9.0 is now required and provides polyfills for several APIs that previously required compiler guards.

Project targets

  • PowerKit.csproj: TargetFrameworkTargetFrameworks, adding net35, netstandard2.0, and net10.0 (order: netstandard2.0;net35;net10.0)

PolyShim version

Updated to PolyShim 2.9.0, which adds net35 polyfills for:

  • Guid.TryParse
  • TimeSpan.TryParse(string, IFormatProvider, out TimeSpan)
  • Assembly.GetCustomAttribute<T>()
  • Stream.CopyTo()

PolyShim also provides NamespaceDummies.cs, which declares dummy types in System.Threading.Tasks (and other namespaces) so that using directives for those namespaces always compile on all targets without any #if guard.

Method-level #if NET40_OR_GREATER || NETSTANDARD || NET guards

The guard is placed around individual methods inside the extension(...) block rather than wrapping the whole file, so sync extensions can be added later without restructuring:

File Guarded members
AsyncEnumerableExtensions.cs Whole file (only async members exist)
StreamExtensions.cs All async CopyToAsync overloads inside extension(Stream source)
TextReaderExtensions.cs ReadLinesAsync inside extension(TextReader reader)
FileExtensions.cs Async ReadAllBytesAsync overloads inside extension(string path)

Partial guards in AssemblyExtensions.cs

No whole-file guard needed. Sync methods (TryGetVersionString, GetManifestResourceString, ExtractManifestResource) are unguarded thanks to PolyShim 2.9.0 polyfills. Only the async method bodies (GetManifestResourceStringAsync, ExtractManifestResourceAsync) remain under a #if NET40_OR_GREATER || NETSTANDARD || NET guard since Task/async requires .NET 4.6+. The using System.Threading; and using System.Threading.Tasks; directives are unconditional — PolyShim's NamespaceDummies.cs ensures they compile on net35.

ExceptionExtensions.cs — no whole-file guard needed

PolyShim polyfills AggregateException, so the file compiles on net35 without a guard. GetSelfAndDescendants uses a guarded return type: IReadOnlyList<Exception> on modern targets (NET40_OR_GREATER || NETSTANDARD || NET) and IList<Exception> on net35 (available since .NET 2.0, no polyfill needed). The method body is shared and returns a concrete List<Exception> in both cases.

Partial guards in EnumerableExtensions.cs

The IReadOnlyList<T> fast-path in LastOrNull is guarded. In ElementAtOrNull, the modern branch uses var (inferred as IReadOnlyList<T>), while the net35 branch uses an explicit IList<T> so that .Count resolves to the interface property rather than the LINQ extension-method group on T[]:

public T? ElementAtOrNull(int index)
{
#if NET40_OR_GREATER || NETSTANDARD || NET
    var list = source as IReadOnlyList<T> ?? source.ToArray();
#else
    IList<T> list = source.ToArray();
#endif
    return index >= 0 && index < list.Count ? list[index] : null;
}

…with PolyShim

Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/62ed1b9c-62a5-4b9f-a9e6-42f951a40b50

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
@Tyrrrz
Copy link
Copy Markdown
Owner

Tyrrrz commented Apr 13, 2026

@copilot please fix conflicts

Copy link
Copy Markdown
Owner

@Tyrrrz Tyrrrz left a comment

Choose a reason for hiding this comment

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

Instead of !NET35 use the NET40_OR_NEWER (or whatever it is) guard @copilot

Comment thread PowerKit/Extensions/AssemblyExtensions.cs Outdated
Comment thread PowerKit/Extensions/EnumerableExtensions.cs Outdated
Comment thread PowerKit/Extensions/GuidExtensions.cs Outdated
Comment thread PowerKit/Extensions/ExceptionExtensions.cs Outdated
Comment thread PowerKit/Extensions/TimeSpanExtensions.cs Outdated
Comment thread PowerKit/PowerKit.csproj Outdated
…ync methods

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 13, 2026

@copilot please fix conflicts

Conflicts resolved in 8c581eb. The AssemblyExtensions.cs conflict (our #if !NET35 guard vs. the new using System.IO and new methods from prime) was merged by keeping the guard and incorporating all the new content. Also added #if !NET35 around the two new async methods in FileExtensions.cs from prime, since Task is unavailable on net35 without Microsoft.Bcl.Async.

…add net10.0 target; simplify ElementAtOrNull

Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/065ab2f6-f4f0-4bb0-923d-620848f5d8b1

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 13, 2026

Instead of !NET35 use the NET40_OR_NEWER (or whatever it is) guard @copilot

Done in 7d0d864 — all guards are now #if NET40_OR_GREATER || NETSTANDARD || NET (covering netstandard2.0 and net10.0 as well as any .NET Framework ≥ 4.0, while excluding net35).

Copilot AI changed the title Add net35 target with compiler guards for APIs unsupported by PolyShim Add net35/net10.0 targets with compiler guards for APIs unsupported by PolyShim Apr 13, 2026
Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/092152bb-90bb-4660-a69c-d821170f96a0

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
…ption> (PolyShim polyfills AggregateException)

Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/56d471b2-e851-414e-987b-f3210dd64367

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 13, 2026

@copilot please fix conflicts

No new commits on prime since our last merge (8c581eb). The branch is conflict-free — origin/prime is already a direct ancestor of our branch.

…s, IEnumerable<Exception> on net35

Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/4ef6a122-f948-4abf-98cb-2834ce1022ee

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
@Tyrrrz Tyrrrz marked this pull request as ready for review April 14, 2026 10:57
Copilot AI review requested due to automatic review settings April 14, 2026 10:57
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@Tyrrrz
Copy link
Copy Markdown
Owner

Tyrrrz commented Apr 14, 2026

@copilot please update PolyShim to v2.9.0, I've added polyfills that should fix some of the issues you've outlined.

…APIs now polyfilled

Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/d1aaa064-db73-483d-b2e7-07ac3af20f6c

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 14, 2026

@copilot please update PolyShim to v2.9.0, I've added polyfills that should fix some of the issues you've outlined.

Done in e49666f. PolyShim 2.9.0 polyfills Guid.TryParse, TimeSpan.TryParse(string, IFormatProvider, out TimeSpan), Assembly.GetCustomAttribute<T>(), and Stream.CopyTo() for net35, so the whole-file guards are now removed from GuidExtensions.cs, TimeSpanExtensions.cs, and AssemblyExtensions.cs. The async methods in AssemblyExtensions.cs still need the NET40_OR_GREATER || NETSTANDARD || NET guard since Task requires .NET 4.6+ even with PolyShim.

Comment thread PowerKit/Extensions/AssemblyExtensions.cs Outdated
Comment thread PowerKit/Extensions/StreamExtensions.cs Outdated
@@ -1,3 +1,4 @@
#if NET40_OR_GREATER || NETSTANDARD || NET
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Wrap the methods, nto the whole file. We might add sync extensions later. @copilot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 74a003f — the #if NET40_OR_GREATER || NETSTANDARD || NET guard is now inside the extension(Stream source) block wrapping the methods, with using directives unconditional at the top of the file.

@@ -1,3 +1,4 @@
#if NET40_OR_GREATER || NETSTANDARD || NET
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Wrap the methods, nto the whole file. We might add sync extensions later. @copilot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in 74a003f — same approach as StreamExtensions.cs: #if NET40_OR_GREATER || NETSTANDARD || NET wraps the ReadLinesAsync method inside the extension(TextReader reader) block, with using directives unconditional at the top.

…Shim provides NamespaceDummies)

Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/4a03314a-3fbb-4070-9f15-85c35c9af036

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Copilot AI and others added 2 commits April 14, 2026 18:53
…ot/add-compiler-guards-for-powerkit

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
…derExtensions.cs; merge prime

Agent-Logs-Url: https://github.com/Tyrrrz/PowerKit/sessions/e33ccf50-1803-4a60-8997-81a3cf566bb5

Co-authored-by: Tyrrrz <1935960+Tyrrrz@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 14, 2026

@copilot please fix conflicts

Conflicts resolved in 74a003f — merged latest prime commits (ArrayPoolExtensions, DirectoryExtensions, EnvironmentExtensions, LockFile, StringExtensions, FileExtensions additions). All three targets build cleanly and all 120 tests pass.

@copilot please update PolyShim to v2.9.0, I've added polyfills that should fix some of the issues you've outlined.

Already done in e49666f — PolyShim is at 2.9.0. The whole-file guards were removed from GuidExtensions.cs, TimeSpanExtensions.cs, and AssemblyExtensions.cs as a result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants