Skip to content

Commit d261a24

Browse files
author
msftbot[bot]
authored
.NET 5 target for Toolkit and HighPerformance packages (#3356)
## Adds the .NET 5 target to `Microsoft.Toolkit.HighPerformance` ## PR Type What kind of change does this PR introduce? <!-- Please uncomment one or more that apply to this PR. --> <!-- - Bugfix --> - Feature <!-- - Code style update (formatting) --> <!-- - Refactoring (no functional changes, no api changes) --> <!-- - Build or CI related changes --> <!-- - Documentation content changes --> <!-- - Sample app changes --> <!-- - Other... Please describe: --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying, or link to a relevant issue. --> The `Microsoft.Toolkit.HighPerformance` package maxes out at .NET Core 3.1. The `Microsoft.Toolkit` package maxes out at .NET Standard 2.1. Additionally, `Microsoft.Toolkit` doesn't have proper nullability annotations, and it reports installing additional dependencies if installed in a .NET 5 apps. The extra dependency is `System.Runtime.CompilerServices.Unsafe` which is actually built-in on .NET 5, but consumers not aware of this would still see the installation prompt from NuGet as reporting an extra indirect dependency. ## What is the new behavior? <!-- Describe how was this issue resolved or changed? --> ✅ Added .NET 5 target to `Microsoft.Toolkit.HighPerformance` ✅ Added .NET 5 target to `Microsoft.Toolkit` ✅ Enabled global nullability annotations to `Microsoft.Toolkit` and improved the codebase. ✅ Enabled C# 9 in both projects, with some extra code tweaks. ## PR Checklist Please check if your PR fulfills the following requirements: - [X] Tested code with current [supported SDKs](../readme.md#supported) - [ ] Pull Request has been submitted to the documentation repository [instructions](..\contributing.md#docs). Link: <!-- docs PR link --> - [ ] Sample in sample app has been added / updated (for bug fixes / features) - [ ] Icon has been created (if new sample) following the [Thumbnail Style Guide and templates](https://github.com/windows-toolkit/WindowsCommunityToolkit-design-assets) - [ ] Tests for the changes have been added (for bug fixes / features) (if applicable) - [X] Header has been added to all new source files (run *build/UpdateHeaders.bat*) - [X] Contains **NO** breaking changes <!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. Please note that breaking changes are likely to be rejected. -->
2 parents 001c5c4 + 9322de6 commit d261a24

File tree

70 files changed

+575
-424
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+575
-424
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#if !NET5_0
6+
7+
namespace System.Runtime.CompilerServices
8+
{
9+
/// <summary>
10+
/// Used to indicate to the compiler that the <c>.locals init</c> flag should not be set in method headers.
11+
/// </summary>
12+
/// <remarks>Internal copy of the .NET 5 attribute.</remarks>
13+
[AttributeUsage(
14+
AttributeTargets.Module |
15+
AttributeTargets.Class |
16+
AttributeTargets.Struct |
17+
AttributeTargets.Interface |
18+
AttributeTargets.Constructor |
19+
AttributeTargets.Method |
20+
AttributeTargets.Property |
21+
AttributeTargets.Event,
22+
Inherited = false)]
23+
internal sealed class SkipLocalsInitAttribute : Attribute
24+
{
25+
}
26+
}
27+
28+
#endif

Microsoft.Toolkit.HighPerformance/Buffers/MemoryOwner{T}.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
using System.Diagnostics;
88
using System.Diagnostics.Contracts;
99
using System.Runtime.CompilerServices;
10-
#if NETCORE_RUNTIME
10+
#if NETCORE_RUNTIME || NET5_0
1111
using System.Runtime.InteropServices;
1212
#endif
1313
using Microsoft.Toolkit.HighPerformance.Buffers.Views;
@@ -183,7 +183,7 @@ public Span<T> Span
183183
ThrowObjectDisposedException();
184184
}
185185

186-
#if NETCORE_RUNTIME
186+
#if NETCORE_RUNTIME || NET5_0
187187
ref T r0 = ref array!.DangerousGetReferenceAt(this.start);
188188

189189
// On .NET Core runtimes, we can manually create a span from the starting reference to

Microsoft.Toolkit.HighPerformance/Buffers/SpanOwner{T}.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
using System.Diagnostics;
88
using System.Diagnostics.Contracts;
99
using System.Runtime.CompilerServices;
10-
#if NETCORE_RUNTIME
10+
#if NETCORE_RUNTIME || NET5_0
1111
using System.Runtime.InteropServices;
1212
#endif
1313
using Microsoft.Toolkit.HighPerformance.Buffers.Views;
@@ -148,7 +148,7 @@ public Span<T> Span
148148
[MethodImpl(MethodImplOptions.AggressiveInlining)]
149149
get
150150
{
151-
#if NETCORE_RUNTIME
151+
#if NETCORE_RUNTIME || NET5_0
152152
ref T r0 = ref array!.DangerousGetReference();
153153

154154
return MemoryMarshal.CreateSpan(ref r0, this.length);

Microsoft.Toolkit.HighPerformance/Buffers/StringPool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Licensed to the .NET Foundation under one or more agreements.
1+
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

Microsoft.Toolkit.HighPerformance/Extensions/ArrayExtensions.1D.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
using System;
66
using System.Diagnostics.Contracts;
77
using System.Runtime.CompilerServices;
8-
#if NETCORE_RUNTIME
8+
#if NETCORE_RUNTIME || NET5_0
99
using System.Runtime.InteropServices;
1010
#endif
1111
using Microsoft.Toolkit.HighPerformance.Enumerables;
@@ -30,7 +30,9 @@ public static partial class ArrayExtensions
3030
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3131
public static ref T DangerousGetReference<T>(this T[] array)
3232
{
33-
#if NETCORE_RUNTIME
33+
#if NET5_0
34+
return ref MemoryMarshal.GetArrayDataReference(array);
35+
#elif NETCORE_RUNTIME
3436
var arrayData = Unsafe.As<RawArrayData>(array)!;
3537
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);
3638

@@ -54,7 +56,12 @@ public static ref T DangerousGetReference<T>(this T[] array)
5456
[MethodImpl(MethodImplOptions.AggressiveInlining)]
5557
public static ref T DangerousGetReferenceAt<T>(this T[] array, int i)
5658
{
57-
#if NETCORE_RUNTIME
59+
#if NET5_0
60+
ref T r0 = ref MemoryMarshal.GetArrayDataReference(array);
61+
ref T ri = ref Unsafe.Add(ref r0, (nint)(uint)i);
62+
63+
return ref ri;
64+
#elif NETCORE_RUNTIME
5865
var arrayData = Unsafe.As<RawArrayData>(array)!;
5966
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);
6067
ref T ri = ref Unsafe.Add(ref r0, (nint)(uint)i);
@@ -203,7 +210,7 @@ public static bool IsCovariant<T>(this T[] array)
203210
/// <summary>
204211
/// Throws an <see cref="OverflowException"/> when the "column" parameter is invalid.
205212
/// </summary>
206-
public static void ThrowOverflowException()
213+
private static void ThrowOverflowException()
207214
{
208215
throw new OverflowException();
209216
}

Microsoft.Toolkit.HighPerformance/Extensions/ArrayExtensions.2D.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,15 +451,15 @@ private static void ThrowArrayTypeMismatchException()
451451
/// <summary>
452452
/// Throws an <see cref="ArgumentOutOfRangeException"/> when the "row" parameter is invalid.
453453
/// </summary>
454-
public static void ThrowArgumentOutOfRangeExceptionForRow()
454+
private static void ThrowArgumentOutOfRangeExceptionForRow()
455455
{
456456
throw new ArgumentOutOfRangeException("row");
457457
}
458458

459459
/// <summary>
460460
/// Throws an <see cref="ArgumentOutOfRangeException"/> when the "column" parameter is invalid.
461461
/// </summary>
462-
public static void ThrowArgumentOutOfRangeExceptionForColumn()
462+
private static void ThrowArgumentOutOfRangeExceptionForColumn()
463463
{
464464
throw new ArgumentOutOfRangeException("column");
465465
}

Microsoft.Toolkit.HighPerformance/Extensions/ArrayExtensions.3D.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ public static bool IsCovariant<T>(this T[,,] array)
316316
/// <summary>
317317
/// Throws an <see cref="ArgumentOutOfRangeException"/> when the "depth" parameter is invalid.
318318
/// </summary>
319-
public static void ThrowArgumentOutOfRangeExceptionForDepth()
319+
private static void ThrowArgumentOutOfRangeExceptionForDepth()
320320
{
321321
throw new ArgumentOutOfRangeException("depth");
322322
}

Microsoft.Toolkit.HighPerformance/Extensions/BoolExtensions.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ public static class BoolExtensions
2121
/// <remarks>This method does not contain branching instructions.</remarks>
2222
[Pure]
2323
[MethodImpl(MethodImplOptions.AggressiveInlining)]
24-
public static byte ToByte(this bool flag)
24+
public static unsafe byte ToByte(this bool flag)
2525
{
26-
return Unsafe.As<bool, byte>(ref flag);
26+
return *(byte*)&flag;
2727
}
2828

2929
/// <summary>
@@ -35,9 +35,9 @@ public static byte ToByte(this bool flag)
3535
[Pure]
3636
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3737
[Obsolete("Use ToByte instead.")]
38-
public static int ToInt(this bool flag)
38+
public static unsafe int ToInt(this bool flag)
3939
{
40-
return Unsafe.As<bool, byte>(ref flag);
40+
return *(byte*)&flag;
4141
}
4242

4343
/// <summary>
@@ -56,9 +56,9 @@ public static int ToInt(this bool flag)
5656
/// </remarks>
5757
[Pure]
5858
[MethodImpl(MethodImplOptions.AggressiveInlining)]
59-
public static int ToBitwiseMask32(this bool flag)
59+
public static unsafe int ToBitwiseMask32(this bool flag)
6060
{
61-
byte rangeFlag = Unsafe.As<bool, byte>(ref flag);
61+
byte rangeFlag = *(byte*)&flag;
6262
int
6363
negativeFlag = rangeFlag - 1,
6464
mask = ~negativeFlag;
@@ -75,9 +75,9 @@ public static int ToBitwiseMask32(this bool flag)
7575
/// <remarks>This method does not contain branching instructions. See additional note in <see cref="ToBitwiseMask32"/>.</remarks>
7676
[Pure]
7777
[MethodImpl(MethodImplOptions.AggressiveInlining)]
78-
public static long ToBitwiseMask64(this bool flag)
78+
public static unsafe long ToBitwiseMask64(this bool flag)
7979
{
80-
byte rangeFlag = Unsafe.As<bool, byte>(ref flag);
80+
byte rangeFlag = *(byte*)&flag;
8181
long
8282
negativeFlag = (long)rangeFlag - 1,
8383
mask = ~negativeFlag;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
#if NET5_0
6+
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Diagnostics.Contracts;
10+
using System.Runtime.CompilerServices;
11+
using System.Runtime.InteropServices;
12+
13+
namespace Microsoft.Toolkit.HighPerformance.Extensions
14+
{
15+
/// <summary>
16+
/// Helpers for working with the <see cref="List{T}"/> type.
17+
/// </summary>
18+
public static class ListExtensions
19+
{
20+
/// <summary>
21+
/// Creates a new <see cref="Span{T}"/> over an input <see cref="List{T}"/> instance.
22+
/// </summary>
23+
/// <typeparam name="T">The type of elements in the input <see cref="List{T}"/> instance.</typeparam>
24+
/// <param name="list">The input <see cref="List{T}"/> instance.</param>
25+
/// <returns>A <see cref="Span{T}"/> instance with the values of <paramref name="list"/>.</returns>
26+
/// <remarks>
27+
/// Note that the returned <see cref="Span{T}"/> is only guaranteed to be valid as long as the items within
28+
/// <paramref name="list"/> are not modified. Doing so might cause the <see cref="List{T}"/> to swap its
29+
/// internal buffer, causing the returned <see cref="Span{T}"/> to become out of date. That means that in this
30+
/// scenario, the <see cref="Span{T}"/> would end up wrapping an array no longer in use. Always make sure to use
31+
/// the returned <see cref="Span{T}"/> while the target <see cref="List{T}"/> is not modified.
32+
/// </remarks>
33+
[Pure]
34+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
35+
public static Span<T> AsSpan<T>(this List<T>? list)
36+
{
37+
return CollectionsMarshal.AsSpan(list);
38+
}
39+
}
40+
}
41+
42+
#endif

Microsoft.Toolkit.HighPerformance/Extensions/ReadOnlySpanExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public static ref T DangerousGetReferenceAt<T>(this ReadOnlySpan<T> span, nint i
138138
/// </returns>
139139
[Pure]
140140
[MethodImpl(MethodImplOptions.AggressiveInlining)]
141-
public static ref readonly T DangerousGetLookupReferenceAt<T>(this ReadOnlySpan<T> span, int i)
141+
public static unsafe ref readonly T DangerousGetLookupReferenceAt<T>(this ReadOnlySpan<T> span, int i)
142142
{
143143
// Check whether the input is in range by first casting both
144144
// operands to uint and then comparing them, as this allows
@@ -156,7 +156,7 @@ public static ref readonly T DangerousGetLookupReferenceAt<T>(this ReadOnlySpan<
156156
// bounds unless the input span was just empty, which for a
157157
// lookup table can just be assumed to always be false.
158158
bool isInRange = (uint)i < (uint)span.Length;
159-
byte rangeFlag = Unsafe.As<bool, byte>(ref isInRange);
159+
byte rangeFlag = *(byte*)&isInRange;
160160
uint
161161
negativeFlag = unchecked(rangeFlag - 1u),
162162
mask = ~negativeFlag,

0 commit comments

Comments
 (0)