Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions PolyShim.Tests/PolyShim.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
<TargetFrameworks Condition="$([MSBuild]::IsOsPlatform('Windows'))"
>$(TargetFrameworks);net462</TargetFrameworks
>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<PropertyGroup>
Expand Down
9 changes: 7 additions & 2 deletions PolyShim/NetCore21/Span.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,17 @@ public Span(T[]? array, int start, int length)
public Span(T[]? array)
: this(array, 0, array?.Length ?? 0) { }

#if !NETFRAMEWORK || NET46_OR_GREATER
#if ALLOW_UNSAFE_BLOCKS
public unsafe Span(void* pointer, int length)
: this(new T[length])
{
// Assume that we're given a block of memory for which this cast is valid
#pragma warning disable CS8500
var source = (T*)pointer;
#pragma warning restore CS8500

for (var i = 0; i < length; i++)
_array![i] = Unsafe.Read<T>((byte*)pointer + i * Unsafe.SizeOf<T>());
_array![i] = source[i];
}
#endif

Expand Down
1 change: 1 addition & 0 deletions PolyShim/PolyShim.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
net35;net40;net45;net461;net462;net48;
net5.0;net7.0;net8.0
</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsPackable>true</IsPackable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<NuGetAudit>false</NuGetAudit>
Expand Down
1 change: 0 additions & 1 deletion PolyShim/PolyShim.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>
4 changes: 4 additions & 0 deletions PolyShim/PolyShim.targets
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
</PropertyGroup>
<!-- Identify feature compatibility -->
<PropertyGroup>
<DefineConstants Condition="'$(AllowUnsafeBlocks)' == 'true'"
>$(DefineConstants);ALLOW_UNSAFE_BLOCKS</DefineConstants
>

<FeatureArrayPool>false</FeatureArrayPool>
<FeatureArrayPool
Condition="@(Reference-&gt;AnyHaveMetadataValue('Identity', 'System.Buffers'))"
Expand Down
42 changes: 38 additions & 4 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ To learn more about the war and how you can help, [click here](https://tyrrrz.me
> To reference this package, you must have the latest major version of the .NET SDK installed.
> This is only required for the build process, and does not affect which version of the runtime you can target.

> [!NOTE]
> Installing this package automatically sets your project's target language version to latest.
> This is required for many polyfills to work, but is also recommended, since **PolyShim** provides the facilities to use modern language features on older frameworks.
> If you have `<LangVersion>` explicitly configured in your project file, make sure it's set to `latest` or newer (e.g. `preview`).

## Features

- Enables compiler support for:
Expand Down Expand Up @@ -140,6 +145,35 @@ var processId = Environment.ProcessId;
> [!NOTE]
> You can find the full list of member polyfills [here](PolyShim/Signatures.md).

### Unsafe code

Certain polyfills that implement low-level memory manipulation features (e.g. `Span<T>.ctor(void*, int)`) require unsafe code to work.
Because **PolyShim** is a source-only package, unsafe code needs to be enabled in your project if you wish to use those polyfills.
To do that, set the `<AllowUnsafeBlocks>` property to `true`:

```xml
<Project>

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>

<!-- Enable unsafe code for polyfills that require it -->
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="PolyShim" Version="..." />
</ItemGroup>

</Project>
```

For example, with unsafe code enabled, you can use stack-allocated span initialization on any version of .NET:

```csharp
Span<byte> buffer = stackalloc byte[256];
```

### Compatibility packages

Some features from newer versions of .NET can also be made available on older frameworks using official compatibility packages published by Microsoft.
Expand Down Expand Up @@ -215,10 +249,10 @@ You can leverage this to prioritize the official implementation wherever possibl
```

```csharp
using System;
using System.Buffers;

// System.Memory is referenced, so this polyfill is disabled
// (the official Span<T> and Memory<T> types are used instead)
Span<byte> buffer = stackalloc byte[256];
Random.Shared.NextBytes(buffer);
// (the official MemoryPool<T> is used instead)
using var buffer = MemoryPool<byte>.Shared.Rent(1024);
var memory = buffer.Memory.Slice(0, 1024);
```
Loading