Merge branch 'master' into jamesmcroft/3506-carousel-automation

This commit is contained in:
James Croft 2020-12-07 19:17:35 +00:00 коммит произвёл GitHub
Родитель 41491ee4f3 9b75c9f910
Коммит 951774d682
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
97 изменённых файлов: 1328 добавлений и 563 удалений

3
.github/PULL_REQUEST_TEMPLATE.md поставляемый
Просмотреть файл

@ -1,5 +1,8 @@
<!-- 🚨 Please Do Not skip any instructions and information mentioned below as they are all required and essential to evaluate and test the PR. By fulfilling all the required information you will be able to reduce the volume of questions and most likely help merge the PR faster 🚨 -->
<!-- 📝 It is preferred if you keep the "☑️ Allow edits by maintainers" checked in the Pull Request Template as it increases collaboration with the Toolkit maintainers by permitting commits to your PR branch (only) created from your fork. This can let us quickly make fixes for minor typos or forgotten StyleCop issues during review without needing to wait on you doing extra work. Let us help you help us! 🎉 -->
## Fixes #
<!-- Add the relevant issue number after the "#" mentioned above (for ex: Fixes #1234) which will automatically close the issue once the PR is merged. -->

Просмотреть файл

@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if !NET5_0
namespace System.Runtime.CompilerServices
{
/// <summary>
/// Used to indicate to the compiler that the <c>.locals init</c> flag should not be set in method headers.
/// </summary>
/// <remarks>Internal copy of the .NET 5 attribute.</remarks>
[AttributeUsage(
AttributeTargets.Module |
AttributeTargets.Class |
AttributeTargets.Struct |
AttributeTargets.Interface |
AttributeTargets.Constructor |
AttributeTargets.Method |
AttributeTargets.Property |
AttributeTargets.Event,
Inherited = false)]
internal sealed class SkipLocalsInitAttribute : Attribute
{
}
}
#endif

Просмотреть файл

@ -7,7 +7,7 @@ using System.Buffers;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
#if NETCORE_RUNTIME
#if NETCORE_RUNTIME || NET5_0
using System.Runtime.InteropServices;
#endif
using Microsoft.Toolkit.HighPerformance.Buffers.Views;
@ -183,7 +183,7 @@ namespace Microsoft.Toolkit.HighPerformance.Buffers
ThrowObjectDisposedException();
}
#if NETCORE_RUNTIME
#if NETCORE_RUNTIME || NET5_0
ref T r0 = ref array!.DangerousGetReferenceAt(this.start);
// On .NET Core runtimes, we can manually create a span from the starting reference to

Просмотреть файл

@ -7,7 +7,7 @@ using System.Buffers;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
#if NETCORE_RUNTIME
#if NETCORE_RUNTIME || NET5_0
using System.Runtime.InteropServices;
#endif
using Microsoft.Toolkit.HighPerformance.Buffers.Views;
@ -148,7 +148,7 @@ namespace Microsoft.Toolkit.HighPerformance.Buffers
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
#if NETCORE_RUNTIME
#if NETCORE_RUNTIME || NET5_0
ref T r0 = ref array!.DangerousGetReference();
return MemoryMarshal.CreateSpan(ref r0, this.length);

Просмотреть файл

@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

Просмотреть файл

@ -5,7 +5,7 @@
using System;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
#if NETCORE_RUNTIME
#if NETCORE_RUNTIME || NET5_0
using System.Runtime.InteropServices;
#endif
using Microsoft.Toolkit.HighPerformance.Enumerables;
@ -30,7 +30,9 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T DangerousGetReference<T>(this T[] array)
{
#if NETCORE_RUNTIME
#if NET5_0
return ref MemoryMarshal.GetArrayDataReference(array);
#elif NETCORE_RUNTIME
var arrayData = Unsafe.As<RawArrayData>(array)!;
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);
@ -54,7 +56,12 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref T DangerousGetReferenceAt<T>(this T[] array, int i)
{
#if NETCORE_RUNTIME
#if NET5_0
ref T r0 = ref MemoryMarshal.GetArrayDataReference(array);
ref T ri = ref Unsafe.Add(ref r0, (nint)(uint)i);
return ref ri;
#elif NETCORE_RUNTIME
var arrayData = Unsafe.As<RawArrayData>(array)!;
ref T r0 = ref Unsafe.As<byte, T>(ref arrayData.Data);
ref T ri = ref Unsafe.Add(ref r0, (nint)(uint)i);
@ -203,7 +210,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// <summary>
/// Throws an <see cref="OverflowException"/> when the "column" parameter is invalid.
/// </summary>
public static void ThrowOverflowException()
private static void ThrowOverflowException()
{
throw new OverflowException();
}

Просмотреть файл

@ -451,7 +451,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// <summary>
/// Throws an <see cref="ArgumentOutOfRangeException"/> when the "row" parameter is invalid.
/// </summary>
public static void ThrowArgumentOutOfRangeExceptionForRow()
private static void ThrowArgumentOutOfRangeExceptionForRow()
{
throw new ArgumentOutOfRangeException("row");
}
@ -459,7 +459,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// <summary>
/// Throws an <see cref="ArgumentOutOfRangeException"/> when the "column" parameter is invalid.
/// </summary>
public static void ThrowArgumentOutOfRangeExceptionForColumn()
private static void ThrowArgumentOutOfRangeExceptionForColumn()
{
throw new ArgumentOutOfRangeException("column");
}

Просмотреть файл

@ -316,7 +316,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// <summary>
/// Throws an <see cref="ArgumentOutOfRangeException"/> when the "depth" parameter is invalid.
/// </summary>
public static void ThrowArgumentOutOfRangeExceptionForDepth()
private static void ThrowArgumentOutOfRangeExceptionForDepth()
{
throw new ArgumentOutOfRangeException("depth");
}

Просмотреть файл

@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics.Contracts;
using System.IO;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.HighPerformance.Buffers;
using Microsoft.Toolkit.HighPerformance.Streams;
using Microsoft.Toolkit.HighPerformance.Streams.Sources;
namespace Microsoft.Toolkit.HighPerformance.Extensions
{
/// <summary>
/// Helpers for working with the <see cref="ArrayPoolBufferWriter{T}"/> type.
/// </summary>
public static class ArrayPoolBufferWriterExtensions
{
/// <summary>
/// Returns a <see cref="Stream"/> that can be used to write to a target an <see cref="ArrayPoolBufferWriter{T}"/> of <see cref="byte"/> instance.
/// </summary>
/// <param name="writer">The target <see cref="ArrayPoolBufferWriter{T}"/> instance.</param>
/// <returns>A <see cref="Stream"/> wrapping <paramref name="writer"/> and writing data to its underlying buffer.</returns>
/// <remarks>The returned <see cref="Stream"/> can only be written to and does not support seeking.</remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Stream AsStream(this ArrayPoolBufferWriter<byte> writer)
{
return new IBufferWriterStream<ArrayBufferWriterOwner>(new ArrayBufferWriterOwner(writer));
}
}
}

Просмотреть файл

@ -21,9 +21,9 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// <remarks>This method does not contain branching instructions.</remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte ToByte(this bool flag)
public static unsafe byte ToByte(this bool flag)
{
return Unsafe.As<bool, byte>(ref flag);
return *(byte*)&flag;
}
/// <summary>
@ -35,9 +35,9 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Obsolete("Use ToByte instead.")]
public static int ToInt(this bool flag)
public static unsafe int ToInt(this bool flag)
{
return Unsafe.As<bool, byte>(ref flag);
return *(byte*)&flag;
}
/// <summary>
@ -56,9 +56,9 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ToBitwiseMask32(this bool flag)
public static unsafe int ToBitwiseMask32(this bool flag)
{
byte rangeFlag = Unsafe.As<bool, byte>(ref flag);
byte rangeFlag = *(byte*)&flag;
int
negativeFlag = rangeFlag - 1,
mask = ~negativeFlag;
@ -75,9 +75,9 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// <remarks>This method does not contain branching instructions. See additional note in <see cref="ToBitwiseMask32"/>.</remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long ToBitwiseMask64(this bool flag)
public static unsafe long ToBitwiseMask64(this bool flag)
{
byte rangeFlag = Unsafe.As<bool, byte>(ref flag);
byte rangeFlag = *(byte*)&flag;
long
negativeFlag = (long)rangeFlag - 1,
mask = ~negativeFlag;

Просмотреть файл

@ -4,8 +4,13 @@
using System;
using System.Buffers;
using System.Diagnostics.Contracts;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.Toolkit.HighPerformance.Buffers;
using Microsoft.Toolkit.HighPerformance.Streams;
using Microsoft.Toolkit.HighPerformance.Streams.Sources;
namespace Microsoft.Toolkit.HighPerformance.Extensions
{
@ -14,6 +19,28 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// </summary>
public static class IBufferWriterExtensions
{
/// <summary>
/// Returns a <see cref="Stream"/> that can be used to write to a target an <see cref="IBufferWriter{T}"/> of <see cref="byte"/> instance.
/// </summary>
/// <param name="writer">The target <see cref="IBufferWriter{T}"/> instance.</param>
/// <returns>A <see cref="Stream"/> wrapping <paramref name="writer"/> and writing data to its underlying buffer.</returns>
/// <remarks>The returned <see cref="Stream"/> can only be written to and does not support seeking.</remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Stream AsStream(this IBufferWriter<byte> writer)
{
if (writer.GetType() == typeof(ArrayPoolBufferWriter<byte>))
{
// If the input writer is of type ArrayPoolBufferWriter<byte>, we can use the type
// specific buffer writer owner to let the JIT elide callvirts when accessing it.
var internalWriter = Unsafe.As<ArrayPoolBufferWriter<byte>>(writer)!;
return new IBufferWriterStream<ArrayBufferWriterOwner>(new ArrayBufferWriterOwner(internalWriter));
}
return new IBufferWriterStream<IBufferWriterOwner>(new IBufferWriterOwner(writer));
}
/// <summary>
/// Writes a value of a specified type into a target <see cref="IBufferWriter{T}"/> instance.
/// </summary>

Просмотреть файл

@ -0,0 +1,42 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if NET5_0
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.Toolkit.HighPerformance.Extensions
{
/// <summary>
/// Helpers for working with the <see cref="List{T}"/> type.
/// </summary>
public static class ListExtensions
{
/// <summary>
/// Creates a new <see cref="Span{T}"/> over an input <see cref="List{T}"/> instance.
/// </summary>
/// <typeparam name="T">The type of elements in the input <see cref="List{T}"/> instance.</typeparam>
/// <param name="list">The input <see cref="List{T}"/> instance.</param>
/// <returns>A <see cref="Span{T}"/> instance with the values of <paramref name="list"/>.</returns>
/// <remarks>
/// Note that the returned <see cref="Span{T}"/> is only guaranteed to be valid as long as the items within
/// <paramref name="list"/> are not modified. Doing so might cause the <see cref="List{T}"/> to swap its
/// internal buffer, causing the returned <see cref="Span{T}"/> to become out of date. That means that in this
/// scenario, the <see cref="Span{T}"/> would end up wrapping an array no longer in use. Always make sure to use
/// the returned <see cref="Span{T}"/> while the target <see cref="List{T}"/> is not modified.
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T>(this List<T>? list)
{
return CollectionsMarshal.AsSpan(list);
}
}
}
#endif

Просмотреть файл

@ -138,7 +138,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// </returns>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref readonly T DangerousGetLookupReferenceAt<T>(this ReadOnlySpan<T> span, int i)
public static unsafe ref readonly T DangerousGetLookupReferenceAt<T>(this ReadOnlySpan<T> span, int i)
{
// Check whether the input is in range by first casting both
// operands to uint and then comparing them, as this allows
@ -156,7 +156,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
// bounds unless the input span was just empty, which for a
// lookup table can just be assumed to always be false.
bool isInRange = (uint)i < (uint)span.Length;
byte rangeFlag = Unsafe.As<bool, byte>(ref isInRange);
byte rangeFlag = *(byte*)&isInRange;
uint
negativeFlag = unchecked(rangeFlag - 1u),
mask = ~negativeFlag,

Просмотреть файл

@ -167,24 +167,24 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
/// <returns>The <typeparamref name="T"/> value read from <paramref name="stream"/>.</returns>
/// <exception cref="InvalidOperationException">Thrown if <paramref name="stream"/> reaches the end.</exception>
#if SPAN_RUNTIME_SUPPORT
// Avoid inlining as we're renting a stack buffer, which
// cause issues if this method was called inside a loop
[MethodImpl(MethodImplOptions.NoInlining)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static T Read<T>(this Stream stream)
where T : unmanaged
{
#if SPAN_RUNTIME_SUPPORT
Span<byte> span = stackalloc byte[Unsafe.SizeOf<T>()];
T result = default;
int length = Unsafe.SizeOf<T>();
if (stream.Read(span) != span.Length)
unsafe
{
ThrowInvalidOperationExceptionForEndOfStream();
if (stream.Read(new Span<byte>(&result, length)) != length)
{
ThrowInvalidOperationExceptionForEndOfStream();
}
}
ref byte r0 = ref MemoryMarshal.GetReference(span);
return Unsafe.ReadUnaligned<T>(ref r0);
return result;
#else
int length = Unsafe.SizeOf<T>();
byte[] buffer = ArrayPool<byte>.Shared.Rent(length);

Просмотреть файл

@ -5,7 +5,7 @@
using System;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
#if !NETCOREAPP3_1
#if NETCOREAPP2_1 || NETSTANDARD
using System.Runtime.InteropServices;
#endif
using Microsoft.Toolkit.HighPerformance.Enumerables;
@ -28,7 +28,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref char DangerousGetReference(this string text)
{
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
return ref Unsafe.AsRef(text.GetPinnableReference());
#elif NETCOREAPP2_1
var stringData = Unsafe.As<RawStringData>(text)!;
@ -50,7 +50,7 @@ namespace Microsoft.Toolkit.HighPerformance.Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref char DangerousGetReferenceAt(this string text, int i)
{
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
ref char r0 = ref Unsafe.AsRef(text.GetPinnableReference());
#elif NETCOREAPP2_1
ref char r0 = ref Unsafe.As<RawStringData>(text)!.Data;

Просмотреть файл

@ -4,7 +4,7 @@
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
using System.Runtime.Intrinsics.X86;
#endif
@ -28,7 +28,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasFlag(uint value, int n)
public static unsafe bool HasFlag(uint value, int n)
{
// Read the n-th bit, downcast to byte
byte flag = (byte)((value >> n) & 1);
@ -40,7 +40,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
// compared the previous computed flag against 0, the assembly
// would have had to perform the test, set the non-zero
// flag and then extend the (byte) result to eax.
return Unsafe.As<byte, bool>(ref flag);
return *(bool*)&flag;
}
/// <summary>
@ -74,7 +74,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasLookupFlag(uint table, int x, int min = 0)
public static unsafe bool HasLookupFlag(uint table, int x, int min = 0)
{
// First, the input value is scaled down by the given minimum.
// This step will be skipped entirely if min is just the default of 0.
@ -91,14 +91,14 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
// as a bool just like in the HasFlag method above, and then returned.
int i = x - min;
bool isInRange = (uint)i < 32u;
byte byteFlag = Unsafe.As<bool, byte>(ref isInRange);
byte byteFlag = *(byte*)&isInRange;
int
negativeFlag = byteFlag - 1,
mask = ~negativeFlag,
shift = unchecked((int)((table >> i) & 1)),
and = shift & mask;
byte result = unchecked((byte)and);
bool valid = Unsafe.As<byte, bool>(ref result);
bool valid = *(bool*)&result;
return valid;
}
@ -194,7 +194,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint SetFlag(uint value, int n, bool flag)
public static unsafe uint SetFlag(uint value, int n, bool flag)
{
// Shift a bit left to the n-th position, negate the
// resulting value and perform an AND with the input value.
@ -210,7 +210,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
// operation. This will always guaranteed to work, thanks to the
// initial code clearing that bit before setting it again.
uint
flag32 = Unsafe.As<bool, byte>(ref flag),
flag32 = *(byte*)&flag,
shift = flag32 << n,
or = and | shift;
@ -235,7 +235,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ExtractRange(uint value, byte start, byte length)
{
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
if (Bmi1.IsSupported)
{
return Bmi1.BitFieldExtract(value, start, length);
@ -283,7 +283,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
loadMask = highBits << start,
storeMask = (flags & highBits) << start;
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
if (Bmi1.IsSupported)
{
return Bmi1.AndNot(loadMask, value) | storeMask;
@ -306,12 +306,12 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasFlag(ulong value, int n)
public static unsafe bool HasFlag(ulong value, int n)
{
// Same logic as the uint version, see that for more info
byte flag = (byte)((value >> n) & 1);
return Unsafe.As<byte, bool>(ref flag);
return *(bool*)&flag;
}
/// <summary>
@ -328,18 +328,18 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasLookupFlag(ulong table, int x, int min = 0)
public static unsafe bool HasLookupFlag(ulong table, int x, int min = 0)
{
int i = x - min;
bool isInRange = (uint)i < 64u;
byte byteFlag = Unsafe.As<bool, byte>(ref isInRange);
byte byteFlag = *(byte*)&isInRange;
int
negativeFlag = byteFlag - 1,
mask = ~negativeFlag,
shift = unchecked((int)((table >> i) & 1)),
and = shift & mask;
byte result = unchecked((byte)and);
bool valid = Unsafe.As<byte, bool>(ref result);
bool valid = *(bool*)&result;
return valid;
}
@ -373,13 +373,13 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong SetFlag(ulong value, int n, bool flag)
public static unsafe ulong SetFlag(ulong value, int n, bool flag)
{
ulong
bit = 1ul << n,
not = ~bit,
and = value & not,
flag64 = Unsafe.As<bool, byte>(ref flag),
flag64 = *(byte*)&flag,
shift = flag64 << n,
or = and | shift;
@ -404,7 +404,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong ExtractRange(ulong value, byte start, byte length)
{
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
if (Bmi1.X64.IsSupported)
{
return Bmi1.X64.BitFieldExtract(value, start, length);
@ -452,7 +452,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers
loadMask = highBits << start,
storeMask = (flags & highBits) << start;
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
if (Bmi1.X64.IsSupported)
{
return Bmi1.X64.AndNot(loadMask, value) | storeMask;

Просмотреть файл

@ -4,7 +4,7 @@
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
using static System.Numerics.BitOperations;
#endif
@ -25,7 +25,7 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int RoundUpPowerOfTwo(int x)
{
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
return 1 << (32 - LeadingZeroCount((uint)(x - 1)));
#else
x--;

Просмотреть файл

@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@ -79,9 +79,6 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
/// Implements <see cref="Count{T}"/> with a sequential search.
/// </summary>
[Pure]
#if NETCOREAPP3_1
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
#endif
private static nint CountSequential<T>(ref T r0, nint length, T value)
where T : IEquatable<T>
{
@ -132,9 +129,6 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
/// Implements <see cref="Count{T}"/> with a vectorized search.
/// </summary>
[Pure]
#if NETCOREAPP3_1
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
#endif
private static nint CountSimd<T>(ref T r0, nint length, T value)
where T : unmanaged, IEquatable<T>
{
@ -161,6 +155,67 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
var partials = Vector<T>.Zero;
// Unrolled vectorized loop, with 8 unrolled iterations. We only run this when the
// current type T is at least 2 bytes in size, otherwise the average chunk length
// would always be too small to be able to trigger the unrolled loop, and the overall
// performance would just be slightly worse due to the additional conditional branches.
if (typeof(T) != typeof(sbyte))
{
while (chunkLength >= Vector<T>.Count * 8)
{
ref T ri0 = ref Unsafe.Add(ref r0, offset + (Vector<T>.Count * 0));
var vi0 = Unsafe.As<T, Vector<T>>(ref ri0);
var ve0 = Vector.Equals(vi0, vc);
partials -= ve0;
ref T ri1 = ref Unsafe.Add(ref r0, offset + (Vector<T>.Count * 1));
var vi1 = Unsafe.As<T, Vector<T>>(ref ri1);
var ve1 = Vector.Equals(vi1, vc);
partials -= ve1;
ref T ri2 = ref Unsafe.Add(ref r0, offset + (Vector<T>.Count * 2));
var vi2 = Unsafe.As<T, Vector<T>>(ref ri2);
var ve2 = Vector.Equals(vi2, vc);
partials -= ve2;
ref T ri3 = ref Unsafe.Add(ref r0, offset + (Vector<T>.Count * 3));
var vi3 = Unsafe.As<T, Vector<T>>(ref ri3);
var ve3 = Vector.Equals(vi3, vc);
partials -= ve3;
ref T ri4 = ref Unsafe.Add(ref r0, offset + (Vector<T>.Count * 4));
var vi4 = Unsafe.As<T, Vector<T>>(ref ri4);
var ve4 = Vector.Equals(vi4, vc);
partials -= ve4;
ref T ri5 = ref Unsafe.Add(ref r0, offset + (Vector<T>.Count * 5));
var vi5 = Unsafe.As<T, Vector<T>>(ref ri5);
var ve5 = Vector.Equals(vi5, vc);
partials -= ve5;
ref T ri6 = ref Unsafe.Add(ref r0, offset + (Vector<T>.Count * 6));
var vi6 = Unsafe.As<T, Vector<T>>(ref ri6);
var ve6 = Vector.Equals(vi6, vc);
partials -= ve6;
ref T ri7 = ref Unsafe.Add(ref r0, offset + (Vector<T>.Count * 7));
var vi7 = Unsafe.As<T, Vector<T>>(ref ri7);
var ve7 = Vector.Equals(vi7, vc);
partials -= ve7;
chunkLength -= Vector<T>.Count * 8;
offset += Vector<T>.Count * 8;
}
}
while (chunkLength >= Vector<T>.Count)
{
ref T ri = ref Unsafe.Add(ref r0, offset);
@ -242,28 +297,22 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
private static unsafe nint GetUpperBound<T>()
where T : unmanaged
{
if (typeof(T) == typeof(byte) ||
typeof(T) == typeof(sbyte) ||
typeof(T) == typeof(bool))
if (typeof(T) == typeof(sbyte))
{
return sbyte.MaxValue;
}
if (typeof(T) == typeof(char) ||
typeof(T) == typeof(ushort) ||
typeof(T) == typeof(short))
if (typeof(T) == typeof(short))
{
return short.MaxValue;
}
if (typeof(T) == typeof(int) ||
typeof(T) == typeof(uint))
if (typeof(T) == typeof(int))
{
return int.MaxValue;
}
if (typeof(T) == typeof(long) ||
typeof(T) == typeof(ulong))
if (typeof(T) == typeof(long))
{
if (sizeof(nint) == sizeof(int))
{

Просмотреть файл

@ -1,4 +1,4 @@
// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@ -21,9 +21,6 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
/// <param name="length">The number of items to hash.</param>
/// <returns>The Djb2 value for the input sequence of items.</returns>
[Pure]
#if NETCOREAPP3_1
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
#endif
public static int GetDjb2HashCode<T>(ref T r0, nint length)
where T : notnull
{
@ -87,9 +84,6 @@ namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
/// faster than <see cref="GetDjb2HashCode{T}"/>, as it can parallelize much of the workload.
/// </remarks>
[Pure]
#if NETCOREAPP3_1
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
#endif
public static unsafe int GetDjb2LikeByteHash(ref byte r0, nint length)
{
int hash = 5381;

Просмотреть файл

@ -17,6 +17,8 @@ using Microsoft.Toolkit.HighPerformance.Memory.Internals;
using Microsoft.Toolkit.HighPerformance.Memory.Views;
using static Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
#pragma warning disable CA2231
namespace Microsoft.Toolkit.HighPerformance.Memory
{
/// <summary>
@ -601,7 +603,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (!(this.instance is null))
if (this.instance is not null)
{
#if SPAN_RUNTIME_SUPPORT
if (this.instance is MemoryManager<T> memoryManager)
@ -738,7 +740,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
/// <returns>A <see cref="MemoryHandle"/> instance wrapping the pinned handle.</returns>
public unsafe MemoryHandle Pin()
{
if (!(this.instance is null))
if (this.instance is not null)
{
if (this.instance is MemoryManager<T> memoryManager)
{
@ -863,7 +865,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
if (!(this.instance is null))
if (this.instance is not null)
{
#if !NETSTANDARD1_4
return HashCode.Combine(

Просмотреть файл

@ -17,6 +17,8 @@ using Microsoft.Toolkit.HighPerformance.Memory.Internals;
using Microsoft.Toolkit.HighPerformance.Memory.Views;
using static Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
#pragma warning disable CA2231
namespace Microsoft.Toolkit.HighPerformance.Memory
{
/// <summary>
@ -615,7 +617,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (!(this.instance is null))
if (this.instance is not null)
{
#if SPAN_RUNTIME_SUPPORT
if (this.instance is MemoryManager<T> memoryManager)
@ -753,7 +755,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
/// <returns>A <see cref="MemoryHandle"/> instance wrapping the pinned handle.</returns>
public unsafe MemoryHandle Pin()
{
if (!(this.instance is null))
if (this.instance is not null)
{
if (this.instance is MemoryManager<T> memoryManager)
{
@ -876,7 +878,7 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode()
{
if (!(this.instance is null))
if (this.instance is not null)
{
#if !NETSTANDARD1_4
return HashCode.Combine(

Просмотреть файл

@ -15,6 +15,8 @@ using Microsoft.Toolkit.HighPerformance.Memory.Views;
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
#endif
#pragma warning disable CS0809, CA1065
namespace Microsoft.Toolkit.HighPerformance.Memory
{
/// <summary>
@ -943,7 +945,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
return array;
}
#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member
/// <inheritdoc cref="ReadOnlySpan{T}.Equals(object)"/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Equals() on Span will always throw an exception. Use == instead.")]
@ -959,7 +960,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
{
throw new NotSupportedException("Microsoft.Toolkit.HighPerformance.ReadOnlySpan2D<T>.GetHashCode() is not supported");
}
#pragma warning restore CS0809
/// <inheritdoc/>
public override string ToString()

Просмотреть файл

@ -15,6 +15,8 @@ using Microsoft.Toolkit.HighPerformance.Memory.Views;
using RuntimeHelpers = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers;
#endif
#pragma warning disable CS0809, CA1065
namespace Microsoft.Toolkit.HighPerformance.Memory
{
/// <summary>
@ -1093,7 +1095,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
return array;
}
#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member
/// <inheritdoc cref="Span{T}.Equals(object)"/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Equals() on Span will always throw an exception. Use == instead.")]
@ -1109,7 +1110,6 @@ namespace Microsoft.Toolkit.HighPerformance.Memory
{
throw new NotSupportedException("Microsoft.Toolkit.HighPerformance.Span2D<T>.GetHashCode() is not supported");
}
#pragma warning restore CS0809
/// <inheritdoc/>
public override string ToString()

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.4;netstandard2.0;netstandard2.1;netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>netstandard1.4;netstandard2.0;netstandard2.1;netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@ -75,6 +75,11 @@
<DefineConstants>NETSTANDARD2_1_OR_GREATER;SPAN_RUNTIME_SUPPORT</DefineConstants>
</PropertyGroup>
</When>
<When Condition=" '$(TargetFramework)' == 'net5.0' ">
<PropertyGroup>
<DefineConstants>NETSTANDARD2_1_OR_GREATER;SPAN_RUNTIME_SUPPORT</DefineConstants>
</PropertyGroup>
</When>
<When Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
<ItemGroup>
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
@ -82,11 +87,12 @@
<PropertyGroup>
<!-- NETCORE_RUNTIME: to avoid issues with APIs that assume a specific memory layout, we define a
.NET Core runtime constant to indicate the either .NET Core 2.1 or .NET Core 3.1. These are
.NET Core runtime constant to indicate either .NET Core 2.1 or .NET Core 3.1. These are
runtimes with the same overall memory layout for objects (in particular: strings, SZ arrays,
and 2D arrays). We can use this constant to make sure that APIs that are exclusively available
for .NET Standard targets do not make any assumption of any internals of the runtime being
actually used by the consumers. -->
and ND arrays). We can use this constant to make sure that APIs that are exclusively available
for .NET Standard targets do not make any assumtpion of any internals of the runtime being
actually used by the consumers. .NET 5.0 would fall into this category as well, but we don't
need to include that target as it offers APIs that don't require runtime-based workarounds.-->
<DefineConstants>NETSTANDARD2_1_OR_GREATER;SPAN_RUNTIME_SUPPORT;NETCORE_RUNTIME</DefineConstants>
</PropertyGroup>
</When>

Просмотреть файл

@ -55,7 +55,7 @@ namespace Microsoft.Toolkit.HighPerformance
/// <summary>
/// Gets a value indicating whether or not the current <see cref="NullableReadOnlyRef{T}"/> instance wraps a valid reference that can be accessed.
/// </summary>
public bool HasValue
public unsafe bool HasValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
@ -63,7 +63,7 @@ namespace Microsoft.Toolkit.HighPerformance
// See comment in NullableRef<T> about this
byte length = unchecked((byte)this.span.Length);
return Unsafe.As<byte, bool>(ref length);
return *(bool*)&length;
}
}

Просмотреть файл

@ -53,7 +53,7 @@ namespace Microsoft.Toolkit.HighPerformance
/// <summary>
/// Gets a value indicating whether or not the current <see cref="NullableRef{T}"/> instance wraps a valid reference that can be accessed.
/// </summary>
public bool HasValue
public unsafe bool HasValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
@ -67,7 +67,7 @@ namespace Microsoft.Toolkit.HighPerformance
// This results in a single movzx instruction on x86-64.
byte length = unchecked((byte)Span.Length);
return Unsafe.As<byte, bool>(ref length);
return *(bool*)&length;
}
}

Просмотреть файл

@ -0,0 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.CompilerServices;
// We can suppress the .init flag for local variables for the entire module.
// This doesn't affect the correctness of methods in this assembly, as none of them
// are relying on the JIT ensuring that all local memory is zeroed out to work. Doing
// this can provide some minor performance benefits, depending on the workload.
[module: SkipLocalsInit]

Просмотреть файл

@ -0,0 +1,76 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if SPAN_RUNTIME_SUPPORT
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Toolkit.HighPerformance.Streams
{
/// <inheritdoc cref="IBufferWriterStream{TWriter}"/>
internal sealed partial class IBufferWriterStream<TWriter>
{
/// <inheritdoc/>
public override void CopyTo(Stream destination, int bufferSize)
{
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
return new ValueTask(Task.FromCanceled(cancellationToken));
}
try
{
Write(buffer.Span);
return default;
}
catch (OperationCanceledException e)
{
return new ValueTask(Task.FromCanceled(e.CancellationToken));
}
catch (Exception e)
{
return new ValueTask(Task.FromException(e));
}
}
/// <inheritdoc/>
public override int Read(Span<byte> buffer)
{
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override void Write(ReadOnlySpan<byte> buffer)
{
MemoryStream.ValidateDisposed(this.disposed);
Span<byte> destination = this.bufferWriter.GetSpan(buffer.Length);
if (!buffer.TryCopyTo(destination))
{
MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite();
}
this.bufferWriter.Advance(buffer.Length);
}
}
}
#endif

Просмотреть файл

@ -0,0 +1,173 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Toolkit.HighPerformance.Streams
{
/// <summary>
/// A <see cref="Stream"/> implementation wrapping an <see cref="IBufferWriter{T}"/> instance.
/// </summary>
/// <typeparam name="TWriter">The type of buffer writer to use.</typeparam>
internal sealed partial class IBufferWriterStream<TWriter> : Stream
where TWriter : struct, IBufferWriter<byte>
{
/// <summary>
/// The target <typeparamref name="TWriter"/> instance to use.
/// </summary>
private readonly TWriter bufferWriter;
/// <summary>
/// Indicates whether or not the current instance has been disposed
/// </summary>
private bool disposed;
/// <summary>
/// Initializes a new instance of the <see cref="IBufferWriterStream{TWriter}"/> class.
/// </summary>
/// <param name="bufferWriter">The target <see cref="IBufferWriter{T}"/> instance to use.</param>
public IBufferWriterStream(TWriter bufferWriter)
{
this.bufferWriter = bufferWriter;
}
/// <inheritdoc/>
public override bool CanRead => false;
/// <inheritdoc/>
public override bool CanSeek => false;
/// <inheritdoc/>
public override bool CanWrite
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => !this.disposed;
}
/// <inheritdoc/>
public override long Length => throw MemoryStream.GetNotSupportedException();
/// <inheritdoc/>
public override long Position
{
get => throw MemoryStream.GetNotSupportedException();
set => throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override void Flush()
{
}
/// <inheritdoc/>
public override Task FlushAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled(cancellationToken);
}
return Task.CompletedTask;
}
/// <inheritdoc/>
public override Task<int> ReadAsync(byte[]? buffer, int offset, int count, CancellationToken cancellationToken)
{
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override Task WriteAsync(byte[]? buffer, int offset, int count, CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
{
return Task.FromCanceled(cancellationToken);
}
try
{
Write(buffer, offset, count);
return Task.CompletedTask;
}
catch (OperationCanceledException e)
{
return Task.FromCanceled(e.CancellationToken);
}
catch (Exception e)
{
return Task.FromException(e);
}
}
/// <inheritdoc/>
public override long Seek(long offset, SeekOrigin origin)
{
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override void SetLength(long value)
{
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override int Read(byte[]? buffer, int offset, int count)
{
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override int ReadByte()
{
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>
public override void Write(byte[]? buffer, int offset, int count)
{
MemoryStream.ValidateDisposed(this.disposed);
MemoryStream.ValidateBuffer(buffer, offset, count);
Span<byte>
source = buffer.AsSpan(offset, count),
destination = this.bufferWriter.GetSpan(count);
if (!source.TryCopyTo(destination))
{
MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite();
}
this.bufferWriter.Advance(count);
}
/// <inheritdoc/>
public override void WriteByte(byte value)
{
MemoryStream.ValidateDisposed(this.disposed);
this.bufferWriter.GetSpan(1)[0] = value;
this.bufferWriter.Advance(1);
}
/// <inheritdoc/>
protected override void Dispose(bool disposing)
{
this.disposed = true;
}
}
}

Просмотреть файл

@ -12,6 +12,23 @@ namespace Microsoft.Toolkit.HighPerformance.Streams
/// </summary>
internal static partial class MemoryStream
{
/// <summary>
/// Gets a standard <see cref="NotSupportedException"/> instance for a stream.
/// </summary>
/// <returns>A <see cref="NotSupportedException"/> with the standard text.</returns>
public static Exception GetNotSupportedException()
{
return new NotSupportedException("The requested operation is not supported for this stream.");
}
/// <summary>
/// Throws a <see cref="NotSupportedException"/> when trying to perform a not supported operation.
/// </summary>
public static void ThrowNotSupportedException()
{
throw GetNotSupportedException();
}
/// <summary>
/// Throws an <see cref="ArgumentException"/> when trying to write too many bytes to the target stream.
/// </summary>
@ -20,14 +37,6 @@ namespace Microsoft.Toolkit.HighPerformance.Streams
throw new ArgumentException("The current stream can't contain the requested input data.");
}
/// <summary>
/// Throws a <see cref="NotSupportedException"/> when trying to set the length of the stream.
/// </summary>
public static void ThrowNotSupportedExceptionForSetLength()
{
throw new NotSupportedException("Setting the length is not supported for this stream.");
}
/// <summary>
/// Throws an <see cref="ArgumentException"/> when using an invalid seek mode.
/// </summary>
@ -77,14 +86,6 @@ namespace Microsoft.Toolkit.HighPerformance.Streams
throw new ArgumentException("The sum of offset and count can't be larger than the buffer length.", "buffer");
}
/// <summary>
/// Throws a <see cref="NotSupportedException"/> when trying to write on a readonly stream.
/// </summary>
private static void ThrowNotSupportedExceptionForCanWrite()
{
throw new NotSupportedException("The current stream doesn't support writing.");
}
/// <summary>
/// Throws an <see cref="ObjectDisposedException"/> when using a disposed <see cref="Stream"/> instance.
/// </summary>

Просмотреть файл

@ -64,7 +64,7 @@ namespace Microsoft.Toolkit.HighPerformance.Streams
{
if (!canWrite)
{
ThrowNotSupportedExceptionForCanWrite();
ThrowNotSupportedException();
}
}

Просмотреть файл

@ -220,7 +220,7 @@ namespace Microsoft.Toolkit.HighPerformance.Streams
/// <inheritdoc/>
public sealed override void SetLength(long value)
{
MemoryStream.ThrowNotSupportedExceptionForSetLength();
throw MemoryStream.GetNotSupportedException();
}
/// <inheritdoc/>

Просмотреть файл

@ -0,0 +1,52 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.HighPerformance.Buffers;
namespace Microsoft.Toolkit.HighPerformance.Streams.Sources
{
/// <summary>
/// An <see cref="IBufferWriter{T}"/> implementation wrapping an <see cref="ArrayPoolBufferWriter{T}"/> instance.
/// </summary>
internal readonly struct ArrayBufferWriterOwner : IBufferWriter<byte>
{
/// <summary>
/// The wrapped <see cref="ArrayPoolBufferWriter{T}"/> array.
/// </summary>
private readonly ArrayPoolBufferWriter<byte> writer;
/// <summary>
/// Initializes a new instance of the <see cref="ArrayBufferWriterOwner"/> struct.
/// </summary>
/// <param name="writer">The wrapped <see cref="ArrayPoolBufferWriter{T}"/> instance.</param>
public ArrayBufferWriterOwner(ArrayPoolBufferWriter<byte> writer)
{
this.writer = writer;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Advance(int count)
{
this.writer.Advance(count);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Memory<byte> GetMemory(int sizeHint = 0)
{
return this.writer.GetMemory(sizeHint);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<byte> GetSpan(int sizeHint = 0)
{
return this.writer.GetSpan(sizeHint);
}
}
}

Просмотреть файл

@ -0,0 +1,52 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.HighPerformance.Buffers;
namespace Microsoft.Toolkit.HighPerformance.Streams.Sources
{
/// <summary>
/// An <see cref="IBufferWriter{T}"/> implementation wrapping an <see cref="IBufferWriter{T}"/> instance.
/// </summary>
internal readonly struct IBufferWriterOwner : IBufferWriter<byte>
{
/// <summary>
/// The wrapped <see cref="ArrayPoolBufferWriter{T}"/> array.
/// </summary>
private readonly IBufferWriter<byte> writer;
/// <summary>
/// Initializes a new instance of the <see cref="IBufferWriterOwner"/> struct.
/// </summary>
/// <param name="writer">The wrapped <see cref="IBufferWriter{T}"/> instance.</param>
public IBufferWriterOwner(IBufferWriter<byte> writer)
{
this.writer = writer;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Advance(int count)
{
this.writer.Advance(count);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Memory<byte> GetMemory(int sizeHint = 0)
{
return this.writer.GetMemory(sizeHint);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<byte> GetSpan(int sizeHint = 0)
{
return this.writer.GetSpan(sizeHint);
}
}
}

Просмотреть файл

@ -1,7 +1,9 @@
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<TargetFrameworks>netstandard1.4;uap10.0;native;net461;netcoreapp3.1</TargetFrameworks>
<!--<TargetFrameworks>netstandard1.4;uap10.0;native;net461;netcoreapp3.1</TargetFrameworks>-->
<!-- Removed 'native' target to unblock CI on VS 16.8, tied to changes breaking workaround for https://github.com/NuGet/Home/issues/5154 -->
<TargetFrameworks>netstandard1.4;uap10.0;net461;netcoreapp3.1</TargetFrameworks>
<DefineConstants>$(DefineConstants);NETFX_CORE</DefineConstants>
<Title>Windows Community Toolkit Notifications</Title>
<Description>

Просмотреть файл

@ -21,6 +21,8 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.Controls
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(nameof(Text), typeof(string), typeof(XamlCodeEditor), new PropertyMetadata(string.Empty));
private ThemeListener _themeListener = new ThemeListener();
public XamlCodeEditor()
{
this.InitializeComponent();
@ -40,7 +42,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.Controls
// Highlight Error Line
XamlCodeRenderer.Decorations.Add(new IModelDeltaDecoration(
range,
new IModelDecorationOptions() { IsWholeLine = true, ClassName = _errorStyle, HoverMessage = new string[] { error.Message }.ToMarkdownString() }));
new IModelDecorationOptions() { IsWholeLine = true, ClassName = ErrorStyle, HoverMessage = new string[] { error.Message }.ToMarkdownString() }));
// Show Glyph Icon
XamlCodeRenderer.Decorations.Add(new IModelDeltaDecoration(
@ -121,10 +123,12 @@ namespace Microsoft.Toolkit.Uwp.SampleApp.Controls
public DateTime TimeSampleEditedLast { get; private set; } = DateTime.MinValue;
private CssLineStyle _errorStyle = new CssLineStyle()
private CssLineStyle ErrorStyle
{
BackgroundColor = new SolidColorBrush(Color.FromArgb(0x00, 0xFF, 0xD6, 0xD6))
};
get => _themeListener.CurrentTheme.Equals(ApplicationTheme.Light) ?
new CssLineStyle() { BackgroundColor = new SolidColorBrush(Color.FromArgb(0x00, 0xFF, 0xD6, 0xD6)) } :
new CssLineStyle() { BackgroundColor = new SolidColorBrush(Color.FromArgb(0x00, 0x66, 0x00, 0x00)) };
}
private CssGlyphStyle _errorIconStyle = new CssGlyphStyle()
{

Просмотреть файл

@ -3,10 +3,9 @@
// See the LICENSE file in the project root for more information.
using System.Threading.Tasks;
using Microsoft.Toolkit.Uwp.Helpers;
using Microsoft.Toolkit.Uwp.Extensions;
using Windows.System;
using Windows.UI.Xaml;
using Microsoft.Toolkit.Uwp.Extensions;
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{

Просмотреть файл

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using Microsoft.Toolkit.Uwp.Extensions;
using Microsoft.Toolkit.Uwp.Helpers;
using Microsoft.Toolkit.Uwp.SampleApp.Pages;
using Microsoft.Toolkit.Uwp.UI.Animations;
@ -147,7 +148,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
ShowSamplePicker(category.Samples, true);
// Then Focus on Picker
DispatcherHelper.ExecuteOnUIThreadAsync(() => SamplePickerGridView.Focus(FocusState.Keyboard));
dispatcherQueue.EnqueueAsync(() => SamplePickerGridView.Focus(FocusState.Keyboard));
}
}
else if (args.IsSettingsInvoked)

Просмотреть файл

@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Linq;
using Microsoft.Toolkit.Uwp.Extensions;
using Microsoft.Toolkit.Uwp.Helpers;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Windows.UI.Xaml;
@ -76,7 +77,7 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
if (e.Key == Windows.System.VirtualKey.Down && SamplePickerGrid.Visibility == Windows.UI.Xaml.Visibility.Visible)
{
// If we try and navigate down out of the textbox (and there's search results), go to the search results.
DispatcherHelper.ExecuteOnUIThreadAsync(() => SamplePickerGridView.Focus(FocusState.Keyboard));
dispatcherQueue.EnqueueAsync(() => SamplePickerGridView.Focus(FocusState.Keyboard));
}
}

Просмотреть файл

@ -7,7 +7,6 @@ using Microsoft.Toolkit.Uwp.Helpers;
using Microsoft.Toolkit.Uwp.SampleApp.Pages;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;
@ -16,6 +15,8 @@ namespace Microsoft.Toolkit.Uwp.SampleApp
{
public sealed partial class Shell
{
private readonly DispatcherQueue dispatcherQueue = DispatcherQueue.GetForCurrentThread();
public static Shell Current { get; private set; }
public Shell()

Просмотреть файл

@ -11,6 +11,7 @@ using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Hosting;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
{
@ -238,7 +239,9 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations.Behaviors
focusedElement = FocusManager.GetFocusedElement();
}
if (focusedElement is UIElement element)
// To prevent Popups (Flyouts...) from triggering the autoscroll, we check if the focused element has a valid parent.
// Popups have no parents, whereas a normal Item would have the ListView as a parent.
if (focusedElement is UIElement element && VisualTreeHelper.GetParent(element) != null)
{
FrameworkElement header = (FrameworkElement)HeaderElement;

Просмотреть файл

@ -6,7 +6,7 @@ using System;
using System.Collections.Generic;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Toolkit.Uwp.Helpers;
using Microsoft.Toolkit.Uwp.Extensions;
using Windows.UI;
using Windows.UI.Composition;
using Windows.UI.Composition.Effects;
@ -102,7 +102,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
var task = new AnimationTask();
task.AnimationSet = animationSet;
task.Task = DispatcherHelper.ExecuteOnUIThreadAsync(
task.Task = visual.DispatcherQueue.EnqueueAsync(
() =>
{
const string sceneName = "PointLightScene";
@ -184,7 +184,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations
}
pointLights[visual] = pointLight;
}, Windows.UI.Core.CoreDispatcherPriority.Normal);
});
animationSet.AddAnimationThroughTask(task);
return animationSet;

Просмотреть файл

@ -162,10 +162,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Extensions
offsetX = offsetX > _maxSpeed ? _maxSpeed : offsetX;
offsetY = offsetY > _maxSpeed ? _maxSpeed : offsetY;
RunInUIThread(dispatcherQueue, () =>
{
_scrollViewer?.ChangeView(_scrollViewer.HorizontalOffset + offsetX, _scrollViewer.VerticalOffset + offsetY, null, true);
});
dispatcherQueue.EnqueueAsync(() => _scrollViewer?.ChangeView(_scrollViewer.HorizontalOffset + offsetX, _scrollViewer.VerticalOffset + offsetY, null, true));
}
}
@ -326,10 +323,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Extensions
if (_oldCursorID != cursorID)
{
RunInUIThread(dispatcherQueue, () =>
{
Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Custom, cursorID);
});
dispatcherQueue.EnqueueAsync(() => Window.Current.CoreWindow.PointerCursor = new CoreCursor(CoreCursorType.Custom, cursorID));
_oldCursorID = cursorID;
}
@ -366,10 +360,5 @@ namespace Microsoft.Toolkit.Uwp.UI.Extensions
return isCursorAvailable;
}
private static async void RunInUIThread(DispatcherQueue dispatcherQueue, Action action)
{
await dispatcherQueue.EnqueueAsync(action, DispatcherQueuePriority.Normal);
}
}
}

Просмотреть файл

@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Windows.Foundation.Metadata;
using Windows.System;
@ -67,7 +68,7 @@ namespace Microsoft.Toolkit.Uwp.Extensions
}
}))
{
taskCompletionSource.SetException(new InvalidOperationException("Failed to enqueue the operation"));
taskCompletionSource.SetException(GetEnqueueException("Failed to enqueue the operation"));
}
return taskCompletionSource.Task;
@ -116,7 +117,7 @@ namespace Microsoft.Toolkit.Uwp.Extensions
}
}))
{
taskCompletionSource.SetException(new InvalidOperationException("Failed to enqueue the operation"));
taskCompletionSource.SetException(GetEnqueueException("Failed to enqueue the operation"));
}
return taskCompletionSource.Task;
@ -149,7 +150,7 @@ namespace Microsoft.Toolkit.Uwp.Extensions
return awaitableResult;
}
return Task.FromException(new InvalidOperationException("The Task returned by function cannot be null."));
return Task.FromException(GetEnqueueException("The Task returned by function cannot be null."));
}
catch (Exception e)
{
@ -173,7 +174,7 @@ namespace Microsoft.Toolkit.Uwp.Extensions
}
else
{
taskCompletionSource.SetException(new InvalidOperationException("The Task returned by function cannot be null."));
taskCompletionSource.SetException(GetEnqueueException("The Task returned by function cannot be null."));
}
}
catch (Exception e)
@ -182,7 +183,7 @@ namespace Microsoft.Toolkit.Uwp.Extensions
}
}))
{
taskCompletionSource.SetException(new InvalidOperationException("Failed to enqueue the operation"));
taskCompletionSource.SetException(GetEnqueueException("Failed to enqueue the operation"));
}
return taskCompletionSource.Task;
@ -212,7 +213,7 @@ namespace Microsoft.Toolkit.Uwp.Extensions
return awaitableResult;
}
return Task.FromException<T>(new InvalidOperationException("The Task returned by function cannot be null."));
return Task.FromException<T>(GetEnqueueException("The Task returned by function cannot be null."));
}
catch (Exception e)
{
@ -236,7 +237,7 @@ namespace Microsoft.Toolkit.Uwp.Extensions
}
else
{
taskCompletionSource.SetException(new InvalidOperationException("The Task returned by function cannot be null."));
taskCompletionSource.SetException(GetEnqueueException("The Task returned by function cannot be null."));
}
}
catch (Exception e)
@ -245,7 +246,7 @@ namespace Microsoft.Toolkit.Uwp.Extensions
}
}))
{
taskCompletionSource.SetException(new InvalidOperationException("Failed to enqueue the operation"));
taskCompletionSource.SetException(GetEnqueueException("Failed to enqueue the operation"));
}
return taskCompletionSource.Task;
@ -253,5 +254,16 @@ namespace Microsoft.Toolkit.Uwp.Extensions
return TryEnqueueAsync(dispatcher, function, priority);
}
/// <summary>
/// Creates an <see cref="InvalidOperationException"/> to return when an enqueue operation fails.
/// </summary>
/// <param name="message">The message of the exception.</param>
/// <returns>An <see cref="InvalidOperationException"/> with a specified message.</returns>
[MethodImpl(MethodImplOptions.NoInlining)]
private static InvalidOperationException GetEnqueueException(string message)
{
return new InvalidOperationException(message);
}
}
}

Просмотреть файл

@ -2,14 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if !NETSTANDARD2_1
#if !NETSTANDARD2_1_OR_GREATER
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>
/// Applied to a method that will never return under any circumstance.
/// </summary>
/// <remarks>Internal copy of the .NET Standard 2.1 attribute.</remarks>
/// <remarks>Internal copy from the BCL attribute.</remarks>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
internal sealed class DoesNotReturnAttribute : Attribute
{

Просмотреть файл

@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if !NETSTANDARD2_1
#if !NETSTANDARD2_1_OR_GREATER
namespace System.Diagnostics.CodeAnalysis
{
@ -10,7 +10,7 @@ namespace System.Diagnostics.CodeAnalysis
/// Specifies that a given <see cref="ParameterValue"/> also indicates
/// whether the method will not return (eg. throw an exception).
/// </summary>
/// <remarks>Internal copy of the .NET Standard 2.1 attribute.</remarks>
/// <remarks>Internal copy from the BCL attribute.</remarks>
[AttributeUsage(AttributeTargets.Parameter)]
internal sealed class DoesNotReturnIfAttribute : Attribute
{

Просмотреть файл

@ -1,18 +0,0 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if !NETSTANDARD2_1
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>
/// Specifies that an output may be <see langword="null"/> even if the corresponding type disallows it.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)]
internal sealed class MaybeNullAttribute : Attribute
{
}
}
#endif

Просмотреть файл

@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if !NETSTANDARD2_1
#if !NETSTANDARD2_1_OR_GREATER
namespace System.Diagnostics.CodeAnalysis
{
@ -10,7 +10,7 @@ namespace System.Diagnostics.CodeAnalysis
/// Specifies that an output will not be <see langword="null"/> even if the corresponding type allows it.
/// Specifies that an input argument was not <see langword="null"/> when the call returns.
/// </summary>
/// <remarks>Internal copy of the .NET Standard 2.1 attribute.</remarks>
/// <remarks>Internal copy from the BCL attribute.</remarks>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue)]
internal sealed class NotNullAttribute : Attribute
{

Просмотреть файл

@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if !NETSTANDARD2_1_OR_GREATER
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>
/// Specifies that the output will be non-null if the named parameter is non-null.
/// </summary>
/// <remarks>Internal copy from the BCL attribute.</remarks>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)]
internal sealed class NotNullIfNotNullAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="NotNullIfNotNullAttribute"/> class.
/// </summary>
/// <param name="parameterName">The associated parameter name. The output will be non-null if the argument to the parameter specified is non-null.</param>
public NotNullIfNotNullAttribute(string parameterName) => ParameterName = parameterName;
/// <summary>
/// Gets the associated parameter name.
/// </summary>
public string ParameterName { get; }
}
}
#endif

Просмотреть файл

@ -0,0 +1,29 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if !NETSTANDARD2_1_OR_GREATER
namespace System.Diagnostics.CodeAnalysis
{
/// <summary>
/// Specifies that when a method returns <see cref="ReturnValue"/>, the parameter will not be null even if the corresponding type allows it.
/// </summary>
/// <remarks>Internal copy from the BCL attribute.</remarks>
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class NotNullWhenAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="NotNullWhenAttribute"/> class.
/// </summary>
/// <param name="returnValue">The return value condition. If the method returns this value, the associated parameter will not be null.</param>
public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
/// <summary>
/// Gets a value indicating whether the annotated variable is not <see langword="null"/>.
/// </summary>
public bool ReturnValue { get; }
}
}
#endif

Просмотреть файл

@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if !NET5_0
namespace System.Runtime.CompilerServices
{
/// <summary>
/// Used to indicate to the compiler that the <c>.locals init</c> flag should not be set in method headers.
/// </summary>
/// <remarks>Internal copy from the BCL attribute.</remarks>
[AttributeUsage(
AttributeTargets.Module |
AttributeTargets.Class |
AttributeTargets.Struct |
AttributeTargets.Interface |
AttributeTargets.Constructor |
AttributeTargets.Method |
AttributeTargets.Property |
AttributeTargets.Event,
Inherited = false)]
internal sealed class SkipLocalsInitAttribute : Attribute
{
}
}
#endif

Просмотреть файл

@ -18,6 +18,7 @@ namespace Microsoft.Toolkit.Collections
/// <typeparam name="TValue">The type of the items in the collection.</typeparam>
[DebuggerDisplay("Key = {Key}, Count = {Count}")]
public class ObservableGroup<TKey, TValue> : ObservableCollection<TValue>, IGrouping<TKey, TValue>, IReadOnlyObservableGroup
where TKey : notnull
{
/// <summary>
/// The cached <see cref="PropertyChangedEventArgs"/> for <see cref="Key"/>
@ -30,7 +31,7 @@ namespace Microsoft.Toolkit.Collections
/// <param name="key">The key for the group.</param>
public ObservableGroup(TKey key)
{
Key = key;
this.key = key;
}
/// <summary>
@ -40,7 +41,7 @@ namespace Microsoft.Toolkit.Collections
public ObservableGroup(IGrouping<TKey, TValue> grouping)
: base(grouping)
{
Key = grouping.Key;
this.key = grouping.Key;
}
/// <summary>
@ -51,7 +52,7 @@ namespace Microsoft.Toolkit.Collections
public ObservableGroup(TKey key, IEnumerable<TValue> collection)
: base(collection)
{
Key = key;
this.key = key;
}
private TKey key;
@ -64,7 +65,7 @@ namespace Microsoft.Toolkit.Collections
get => this.key;
set
{
if (!EqualityComparer<TKey>.Default.Equals(this.key, value))
if (!EqualityComparer<TKey>.Default.Equals(this.key!, value))
{
this.key = value;

Просмотреть файл

@ -4,11 +4,10 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Collections
{
/// <summary>
@ -17,6 +16,7 @@ namespace Microsoft.Toolkit.Collections
/// <typeparam name="TKey">The type of the group key.</typeparam>
/// <typeparam name="TValue">The type of the items in the collection.</typeparam>
public sealed class ObservableGroupedCollection<TKey, TValue> : ObservableCollection<ObservableGroup<TKey, TValue>>
where TKey : notnull
{
/// <summary>
/// Initializes a new instance of the <see cref="ObservableGroupedCollection{TKey, TValue}"/> class.
@ -30,7 +30,7 @@ namespace Microsoft.Toolkit.Collections
/// </summary>
/// <param name="collection">The initial data to add in the grouped collection.</param>
public ObservableGroupedCollection(IEnumerable<IGrouping<TKey, TValue>> collection)
: base(collection.Select(c => new ObservableGroup<TKey, TValue>(c)))
: base(collection.Select(static c => new ObservableGroup<TKey, TValue>(c)))
{
}
@ -40,11 +40,11 @@ namespace Microsoft.Toolkit.Collections
/// <param name="list">The resulting <see cref="List{T}"/>, if one was in use.</param>
/// <returns>Whether or not a <see cref="List{T}"/> instance has been found.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal bool TryGetList(out List<ObservableGroup<TKey, TValue>>? list)
internal bool TryGetList([NotNullWhen(true)] out List<ObservableGroup<TKey, TValue>>? list)
{
list = Items as List<ObservableGroup<TKey, TValue>>;
return !(list is null);
return list is not null;
}
}
}

Просмотреть файл

@ -8,8 +8,6 @@ using System.Diagnostics.Contracts;
using System.Linq;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Collections
{
/// <summary>
@ -28,11 +26,17 @@ namespace Microsoft.Toolkit.Collections
/// <exception cref="InvalidOperationException">The target group does not exist.</exception>
[Pure]
public static ObservableGroup<TKey, TValue> First<TKey, TValue>(this ObservableGroupedCollection<TKey, TValue> source, TKey key)
where TKey : notnull
{
ObservableGroup<TKey, TValue>? group = source.FirstOrDefault(key);
if (group is null)
{
static void ThrowArgumentExceptionForKeyNotFound()
{
throw new InvalidOperationException("The requested key was not present in the collection");
}
ThrowArgumentExceptionForKeyNotFound();
}
@ -49,10 +53,11 @@ namespace Microsoft.Toolkit.Collections
/// <returns>The first group matching <paramref name="key"/> or null.</returns>
[Pure]
public static ObservableGroup<TKey, TValue>? FirstOrDefault<TKey, TValue>(this ObservableGroupedCollection<TKey, TValue> source, TKey key)
where TKey : notnull
{
if (source.TryGetList(out var list))
{
foreach (var group in list!)
foreach (var group in list)
{
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
{
@ -63,19 +68,16 @@ namespace Microsoft.Toolkit.Collections
return null;
}
// Fallback method
[MethodImpl(MethodImplOptions.NoInlining)]
static ObservableGroup<TKey, TValue>? FirstOrDefaultWithLinq(ObservableGroupedCollection<TKey, TValue> source, TKey key)
{
return source.FirstOrDefault(group => EqualityComparer<TKey>.Default.Equals(group.Key, key));
}
return FirstOrDefaultWithLinq(source, key);
}
/// <summary>
/// Slow path for <see cref="First{TKey,TValue}"/>.
/// </summary>
[Pure]
[MethodImpl(MethodImplOptions.NoInlining)]
private static ObservableGroup<TKey, TValue>? FirstOrDefaultWithLinq<TKey, TValue>(
ObservableGroupedCollection<TKey, TValue> source,
TKey key)
=> source.FirstOrDefault(group => EqualityComparer<TKey>.Default.Equals(group.Key, key));
/// <summary>
/// Return the element at position <paramref name="index"/> from the first group with <paramref name="key"/> key.
/// </summary>
@ -92,6 +94,7 @@ namespace Microsoft.Toolkit.Collections
this ObservableGroupedCollection<TKey, TValue> source,
TKey key,
int index)
where TKey : notnull
=> source.First(key)[index];
/// <summary>
@ -104,17 +107,18 @@ namespace Microsoft.Toolkit.Collections
/// <param name="index">The index of the item from the targeted group.</param>
/// <returns>The element or default(TValue) if it does not exist.</returns>
[Pure]
public static TValue ElementAtOrDefault<TKey, TValue>(
public static TValue? ElementAtOrDefault<TKey, TValue>(
this ObservableGroupedCollection<TKey, TValue> source,
TKey key,
int index)
where TKey : notnull
{
var group = source.FirstOrDefault(key);
if (group is null ||
(uint)index >= (uint)group.Count)
{
return default!;
return default;
}
return group[index];
@ -133,6 +137,7 @@ namespace Microsoft.Toolkit.Collections
this ObservableGroupedCollection<TKey, TValue> source,
TKey key,
TValue value)
where TKey : notnull
=> AddGroup(source, key, new[] { value });
/// <summary>
@ -148,6 +153,7 @@ namespace Microsoft.Toolkit.Collections
this ObservableGroupedCollection<TKey, TValue> source,
TKey key,
params TValue[] collection)
where TKey : notnull
=> source.AddGroup(key, (IEnumerable<TValue>)collection);
/// <summary>
@ -163,6 +169,7 @@ namespace Microsoft.Toolkit.Collections
this ObservableGroupedCollection<TKey, TValue> source,
TKey key,
IEnumerable<TValue> collection)
where TKey : notnull
{
var group = new ObservableGroup<TKey, TValue>(key, collection);
source.Add(group);
@ -184,6 +191,7 @@ namespace Microsoft.Toolkit.Collections
this ObservableGroupedCollection<TKey, TValue> source,
TKey key,
TValue item)
where TKey : notnull
{
var group = source.FirstOrDefault(key);
@ -215,6 +223,7 @@ namespace Microsoft.Toolkit.Collections
TKey key,
int index,
TValue item)
where TKey : notnull
{
var existingGroup = source.First(key);
existingGroup.Insert(index, item);
@ -239,6 +248,7 @@ namespace Microsoft.Toolkit.Collections
TKey key,
int index,
TValue item)
where TKey : notnull
{
var existingGroup = source.First(key);
existingGroup[index] = item;
@ -257,11 +267,12 @@ namespace Microsoft.Toolkit.Collections
public static void RemoveGroup<TKey, TValue>(
this ObservableGroupedCollection<TKey, TValue> source,
TKey key)
where TKey : notnull
{
if (source.TryGetList(out var list))
{
var index = 0;
foreach (var group in list!)
foreach (var group in list)
{
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
{
@ -275,26 +286,24 @@ namespace Microsoft.Toolkit.Collections
}
else
{
RemoveGroupWithLinq(source, key);
}
}
/// <summary>
/// Slow path for <see cref="RemoveGroup{TKey,TValue}"/>.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
private static void RemoveGroupWithLinq<TKey, TValue>(ObservableGroupedCollection<TKey, TValue> source, TKey key)
{
var index = 0;
foreach (var group in source)
{
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
// Fallback method
[MethodImpl(MethodImplOptions.NoInlining)]
static void RemoveGroupWithLinq(ObservableGroupedCollection<TKey, TValue> source, TKey key)
{
source.RemoveAt(index);
return;
var index = 0;
foreach (var group in source)
{
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
{
source.RemoveAt(index);
return;
}
index++;
}
}
index++;
RemoveGroupWithLinq(source, key);
}
}
@ -313,11 +322,12 @@ namespace Microsoft.Toolkit.Collections
TKey key,
TValue item,
bool removeGroupIfEmpty = true)
where TKey : notnull
{
if (source.TryGetList(out var list))
{
var index = 0;
foreach (var group in list!)
foreach (var group in list)
{
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
{
@ -336,36 +346,34 @@ namespace Microsoft.Toolkit.Collections
}
else
{
RemoveItemWithLinq(source, key, item, removeGroupIfEmpty);
}
}
/// <summary>
/// Slow path for <see cref="RemoveItem{TKey,TValue}"/>.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
private static void RemoveItemWithLinq<TKey, TValue>(
ObservableGroupedCollection<TKey, TValue> source,
TKey key,
TValue item,
bool removeGroupIfEmpty)
{
var index = 0;
foreach (var group in source)
{
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
// Fallback method
[MethodImpl(MethodImplOptions.NoInlining)]
static void RemoveItemWithLinq(
ObservableGroupedCollection<TKey, TValue> source,
TKey key,
TValue item,
bool removeGroupIfEmpty)
{
if (group.Remove(item) &&
removeGroupIfEmpty &&
group.Count == 0)
var index = 0;
foreach (var group in source)
{
source.RemoveAt(index);
}
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
{
if (group.Remove(item) &&
removeGroupIfEmpty &&
group.Count == 0)
{
source.RemoveAt(index);
}
return;
return;
}
index++;
}
}
index++;
RemoveItemWithLinq(source, key, item, removeGroupIfEmpty);
}
}
@ -385,11 +393,12 @@ namespace Microsoft.Toolkit.Collections
TKey key,
int index,
bool removeGroupIfEmpty = true)
where TKey : notnull
{
if (source.TryGetList(out var list))
{
var groupIndex = 0;
foreach (var group in list!)
foreach (var group in list)
{
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
{
@ -408,45 +417,35 @@ namespace Microsoft.Toolkit.Collections
}
else
{
// Fallback method
[MethodImpl(MethodImplOptions.NoInlining)]
static void RemoveItemAtWithLinq(
ObservableGroupedCollection<TKey, TValue> source,
TKey key,
int index,
bool removeGroupIfEmpty)
{
var groupIndex = 0;
foreach (var group in source)
{
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
{
group.RemoveAt(index);
if (removeGroupIfEmpty && group.Count == 0)
{
source.RemoveAt(groupIndex);
}
return;
}
groupIndex++;
}
}
RemoveItemAtWithLinq(source, key, index, removeGroupIfEmpty);
}
}
/// <summary>
/// Slow path for <see cref="RemoveItemAt{TKey,TValue}"/>.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
private static void RemoveItemAtWithLinq<TKey, TValue>(
ObservableGroupedCollection<TKey, TValue> source,
TKey key,
int index,
bool removeGroupIfEmpty)
{
var groupIndex = 0;
foreach (var group in source)
{
if (EqualityComparer<TKey>.Default.Equals(group.Key, key))
{
group.RemoveAt(index);
if (removeGroupIfEmpty && group.Count == 0)
{
source.RemoveAt(groupIndex);
}
return;
}
groupIndex++;
}
}
/// <summary>
/// Throws a new <see cref="InvalidOperationException"/> when a key is not found.
/// </summary>
private static void ThrowArgumentExceptionForKeyNotFound()
{
throw new InvalidOperationException("The requested key was not present in the collection");
}
}
}

Просмотреть файл

@ -14,6 +14,7 @@ namespace Microsoft.Toolkit.Collections
/// <typeparam name="TKey">The type of the group key.</typeparam>
/// <typeparam name="TValue">The type of the items in the collection.</typeparam>
public sealed class ReadOnlyObservableGroup<TKey, TValue> : ReadOnlyObservableCollection<TValue>, IGrouping<TKey, TValue>, IReadOnlyObservableGroup
where TKey : notnull
{
/// <summary>
/// Initializes a new instance of the <see cref="ReadOnlyObservableGroup{TKey, TValue}"/> class.

Просмотреть файл

@ -17,15 +17,16 @@ namespace Microsoft.Toolkit.Collections
/// <typeparam name="TKey">The type of the group key.</typeparam>
/// <typeparam name = "TValue" > The type of the items in the collection.</typeparam>
public sealed class ReadOnlyObservableGroupedCollection<TKey, TValue> : ReadOnlyObservableCollection<ReadOnlyObservableGroup<TKey, TValue>>
where TKey : notnull
{
/// <summary>
/// Initializes a new instance of the <see cref="ReadOnlyObservableGroupedCollection{TKey, TValue}"/> class.
/// </summary>
/// <param name="collection">The source collection to wrap.</param>
public ReadOnlyObservableGroupedCollection(ObservableGroupedCollection<TKey, TValue> collection)
: this(collection.Select(g => new ReadOnlyObservableGroup<TKey, TValue>(g)))
: this(collection.Select(static g => new ReadOnlyObservableGroup<TKey, TValue>(g)))
{
((INotifyCollectionChanged)collection).CollectionChanged += this.OnSourceCollectionChanged;
((INotifyCollectionChanged)collection).CollectionChanged += OnSourceCollectionChanged;
}
/// <summary>
@ -42,14 +43,14 @@ namespace Microsoft.Toolkit.Collections
/// </summary>
/// <param name="collection">The initial data to add in the grouped collection.</param>
public ReadOnlyObservableGroupedCollection(IEnumerable<IGrouping<TKey, TValue>> collection)
: this(collection.Select(g => new ReadOnlyObservableGroup<TKey, TValue>(g.Key, g)))
: this(collection.Select(static g => new ReadOnlyObservableGroup<TKey, TValue>(g.Key, g)))
{
}
private void OnSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void OnSourceCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
// Even if the NotifyCollectionChangedEventArgs allows multiple items, the actual implementation is only
// reporting the changes one by one. We consider only this case for now.
// Even if NotifyCollectionChangedEventArgs allows multiple items, the actual implementation
// is only reporting the changes one by one. We consider only this case for now.
if (e.OldItems?.Count > 1 || e.NewItems?.Count > 1)
{
static void ThrowNotSupportedException()
@ -64,23 +65,33 @@ namespace Microsoft.Toolkit.Collections
ThrowNotSupportedException();
}
var newItem = e.NewItems?.Cast<ObservableGroup<TKey, TValue>>()?.FirstOrDefault();
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
Items.Insert(e.NewStartingIndex, new ReadOnlyObservableGroup<TKey, TValue>(newItem));
case NotifyCollectionChangedAction.Add or NotifyCollectionChangedAction.Replace:
// We only need to find the new item if the operation is either add or remove. In this
// case we just directly find the first item that was modified, or throw if it's not present.
// This normally never happens anyway - add and replace should always have a target element.
ObservableGroup<TKey, TValue> newItem = e.NewItems!.Cast<ObservableGroup<TKey, TValue>>().First();
if (e.Action == NotifyCollectionChangedAction.Add)
{
Items.Insert(e.NewStartingIndex, new ReadOnlyObservableGroup<TKey, TValue>(newItem));
}
else
{
Items[e.OldStartingIndex] = new ReadOnlyObservableGroup<TKey, TValue>(newItem);
}
break;
case NotifyCollectionChangedAction.Move:
// Our inner Items list is our own ObservableCollection<ReadOnlyObservableGroup<TKey, TValue>> so we can safely cast Items to its concrete type here.
((ObservableCollection<ReadOnlyObservableGroup<TKey, TValue>>)Items).Move(e.OldStartingIndex, e.NewStartingIndex);
break;
case NotifyCollectionChangedAction.Remove:
Items.RemoveAt(e.OldStartingIndex);
break;
case NotifyCollectionChangedAction.Replace:
Items[e.OldStartingIndex] = new ReadOnlyObservableGroup<TKey, TValue>(newItem);
break;
case NotifyCollectionChangedAction.Reset:
Items.Clear();
break;

Просмотреть файл

@ -9,8 +9,6 @@ using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -6,8 +6,6 @@ using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -8,8 +8,6 @@
using System;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -5,8 +5,6 @@
using System;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -11,8 +11,6 @@ using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Extensions;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -8,8 +8,6 @@ using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Extensions;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -6,8 +6,6 @@ using System;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -5,8 +5,6 @@
using System;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -6,8 +6,6 @@ using System;
using System.IO;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -6,7 +6,7 @@ using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
#nullable enable
#pragma warning disable CS8777
namespace Microsoft.Toolkit.Diagnostics
{
@ -43,9 +43,7 @@ namespace Microsoft.Toolkit.Diagnostics
{
if (!string.IsNullOrEmpty(text))
{
#pragma warning disable CS8777 // Does not return when text is null
return;
#pragma warning restore CS8777
}
ThrowHelper.ThrowArgumentExceptionForIsNotNullOrEmpty(text, name);
@ -97,9 +95,7 @@ namespace Microsoft.Toolkit.Diagnostics
{
if (!string.IsNullOrWhiteSpace(text))
{
#pragma warning disable CS8777 // Does not return when text is null
return;
#pragma warning restore CS8777
}
ThrowHelper.ThrowArgumentExceptionForIsNotNullOrWhiteSpace(text, name);
@ -117,9 +113,7 @@ namespace Microsoft.Toolkit.Diagnostics
{
if (!string.IsNullOrWhiteSpace(text))
{
#pragma warning disable CS8777 // Does not return when text is null
return;
#pragma warning restore CS8777
}
ThrowHelper.ThrowArgumentExceptionForIsNotNullOrWhiteSpace(text, name);

Просмотреть файл

@ -6,8 +6,6 @@ using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -10,8 +10,6 @@ using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Extensions;
#endif
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>
@ -70,7 +68,7 @@ namespace Microsoft.Toolkit.Diagnostics
public static void IsNotNull<T>([NotNull] T? value, string name)
where T : class
{
if (!(value is null))
if (value is not null)
{
return;
}
@ -90,7 +88,7 @@ namespace Microsoft.Toolkit.Diagnostics
public static void IsNotNull<T>([NotNull] T? value, string name)
where T : struct
{
if (!(value is null))
if (value is not null)
{
return;
}
@ -198,7 +196,7 @@ namespace Microsoft.Toolkit.Diagnostics
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void IsNotAssignableToType<T>(object value, string name)
{
if (!(value is T))
if (value is not T)
{
return;
}

Просмотреть файл

@ -7,8 +7,6 @@ using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Extensions;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -7,8 +7,6 @@ using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Extensions;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -7,8 +7,6 @@ using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Extensions;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -8,8 +8,6 @@ using System.IO;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Extensions;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -6,8 +6,6 @@ using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -8,8 +8,6 @@ using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.Toolkit.Extensions;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -8,8 +8,6 @@ using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using Microsoft.Toolkit.Extensions;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>

Просмотреть файл

@ -11,8 +11,6 @@ using System.Runtime.InteropServices;
#endif
using System.Threading;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>
@ -40,7 +38,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArrayTypeMismatchException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArrayTypeMismatchException<T>(string message)
public static T ThrowArrayTypeMismatchException<T>(string? message)
{
throw new ArrayTypeMismatchException(message);
}
@ -54,7 +52,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArrayTypeMismatchException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArrayTypeMismatchException<T>(string message, Exception innerException)
public static T ThrowArrayTypeMismatchException<T>(string? message, Exception? innerException)
{
throw new ArrayTypeMismatchException(message, innerException);
}
@ -79,7 +77,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentException<T>(string message)
public static T ThrowArgumentException<T>(string? message)
{
throw new ArgumentException(message);
}
@ -93,7 +91,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentException<T>(string message, Exception innerException)
public static T ThrowArgumentException<T>(string? message, Exception? innerException)
{
throw new ArgumentException(message, innerException);
}
@ -107,7 +105,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentException<T>(string name, string message)
public static T ThrowArgumentException<T>(string? name, string? message)
{
throw new ArgumentException(message, name);
}
@ -122,7 +120,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentException<T>(string name, string message, Exception innerException)
public static T ThrowArgumentException<T>(string? name, string? message, Exception? innerException)
{
throw new ArgumentException(message, name, innerException);
}
@ -147,7 +145,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentNullException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentNullException<T>(string name)
public static T ThrowArgumentNullException<T>(string? name)
{
throw new ArgumentNullException(name);
}
@ -161,7 +159,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentNullException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentNullException<T>(string name, Exception innerException)
public static T ThrowArgumentNullException<T>(string? name, Exception? innerException)
{
throw new ArgumentNullException(name, innerException);
}
@ -175,7 +173,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentNullException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentNullException<T>(string name, string message)
public static T ThrowArgumentNullException<T>(string? name, string? message)
{
throw new ArgumentNullException(name, message);
}
@ -200,7 +198,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentOutOfRangeException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentOutOfRangeException<T>(string name)
public static T ThrowArgumentOutOfRangeException<T>(string? name)
{
throw new ArgumentOutOfRangeException(name);
}
@ -214,7 +212,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentOutOfRangeException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentOutOfRangeException<T>(string name, Exception innerException)
public static T ThrowArgumentOutOfRangeException<T>(string? name, Exception? innerException)
{
throw new ArgumentOutOfRangeException(name, innerException);
}
@ -228,7 +226,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentOutOfRangeException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentOutOfRangeException<T>(string name, string message)
public static T ThrowArgumentOutOfRangeException<T>(string? name, string? message)
{
throw new ArgumentOutOfRangeException(name, message);
}
@ -243,7 +241,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ArgumentOutOfRangeException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowArgumentOutOfRangeException<T>(string name, object value, string message)
public static T ThrowArgumentOutOfRangeException<T>(string? name, object? value, string? message)
{
throw new ArgumentOutOfRangeException(name, value, message);
}
@ -269,7 +267,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="COMException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowCOMException<T>(string message)
public static T ThrowCOMException<T>(string? message)
{
throw new COMException(message);
}
@ -283,7 +281,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="COMException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowCOMException<T>(string message, Exception innerException)
public static T ThrowCOMException<T>(string? message, Exception? innerException)
{
throw new COMException(message, innerException);
}
@ -297,7 +295,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="COMException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowCOMException<T>(string message, int error)
public static T ThrowCOMException<T>(string? message, int error)
{
throw new COMException(message, error);
}
@ -322,7 +320,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ExternalException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowExternalException<T>(string message)
public static T ThrowExternalException<T>(string? message)
{
throw new ExternalException(message);
}
@ -336,7 +334,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ExternalException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowExternalException<T>(string message, Exception innerException)
public static T ThrowExternalException<T>(string? message, Exception? innerException)
{
throw new ExternalException(message, innerException);
}
@ -350,7 +348,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ExternalException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowExternalException<T>(string message, int error)
public static T ThrowExternalException<T>(string? message, int error)
{
throw new ExternalException(message, error);
}
@ -376,7 +374,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="FormatException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowFormatException<T>(string message)
public static T ThrowFormatException<T>(string? message)
{
throw new FormatException(message);
}
@ -390,7 +388,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="FormatException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowFormatException<T>(string message, Exception innerException)
public static T ThrowFormatException<T>(string? message, Exception? innerException)
{
throw new FormatException(message, innerException);
}
@ -416,7 +414,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="InsufficientMemoryException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowInsufficientMemoryException<T>(string message)
public static T ThrowInsufficientMemoryException<T>(string? message)
{
throw new InsufficientMemoryException(message);
}
@ -430,7 +428,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="InsufficientMemoryException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowInsufficientMemoryException<T>(string message, Exception innerException)
public static T ThrowInsufficientMemoryException<T>(string? message, Exception? innerException)
{
throw new InsufficientMemoryException(message, innerException);
}
@ -456,7 +454,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="InvalidDataException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowInvalidDataException<T>(string message)
public static T ThrowInvalidDataException<T>(string? message)
{
throw new InvalidDataException(message);
}
@ -470,7 +468,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="InvalidDataException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowInvalidDataException<T>(string message, Exception innerException)
public static T ThrowInvalidDataException<T>(string? message, Exception? innerException)
{
throw new InvalidDataException(message, innerException);
}
@ -495,7 +493,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="InvalidOperationException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowInvalidOperationException<T>(string message)
public static T ThrowInvalidOperationException<T>(string? message)
{
throw new InvalidOperationException(message);
}
@ -509,7 +507,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="InvalidOperationException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowInvalidOperationException<T>(string message, Exception innerException)
public static T ThrowInvalidOperationException<T>(string? message, Exception? innerException)
{
throw new InvalidOperationException(message, innerException);
}
@ -534,7 +532,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="LockRecursionException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowLockRecursionException<T>(string message)
public static T ThrowLockRecursionException<T>(string? message)
{
throw new LockRecursionException(message);
}
@ -548,7 +546,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="LockRecursionException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowLockRecursionException<T>(string message, Exception innerException)
public static T ThrowLockRecursionException<T>(string? message, Exception? innerException)
{
throw new LockRecursionException(message, innerException);
}
@ -573,7 +571,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="MissingFieldException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowMissingFieldException<T>(string message)
public static T ThrowMissingFieldException<T>(string? message)
{
throw new MissingFieldException(message);
}
@ -587,7 +585,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="MissingFieldException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowMissingFieldException<T>(string message, Exception innerException)
public static T ThrowMissingFieldException<T>(string? message, Exception? innerException)
{
throw new MissingFieldException(message, innerException);
}
@ -602,7 +600,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="MissingFieldException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowMissingFieldException<T>(string className, string fieldName)
public static T ThrowMissingFieldException<T>(string? className, string? fieldName)
{
throw new MissingFieldException(className, fieldName);
}
@ -628,7 +626,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="MissingMemberException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowMissingMemberException<T>(string message)
public static T ThrowMissingMemberException<T>(string? message)
{
throw new MissingMemberException(message);
}
@ -642,7 +640,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="MissingMemberException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowMissingMemberException<T>(string message, Exception innerException)
public static T ThrowMissingMemberException<T>(string? message, Exception? innerException)
{
throw new MissingMemberException(message, innerException);
}
@ -657,7 +655,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="MissingMemberException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowMissingMemberException<T>(string className, string memberName)
public static T ThrowMissingMemberException<T>(string? className, string? memberName)
{
throw new MissingMemberException(className, memberName);
}
@ -683,7 +681,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="MissingMethodException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowMissingMethodException<T>(string message)
public static T ThrowMissingMethodException<T>(string? message)
{
throw new MissingMethodException(message);
}
@ -697,7 +695,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="MissingMethodException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowMissingMethodException<T>(string message, Exception innerException)
public static T ThrowMissingMethodException<T>(string? message, Exception? innerException)
{
throw new MissingMethodException(message, innerException);
}
@ -712,7 +710,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="MissingMethodException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowMissingMethodException<T>(string className, string methodName)
public static T ThrowMissingMethodException<T>(string? className, string? methodName)
{
throw new MissingMethodException(className, methodName);
}
@ -738,7 +736,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="NotSupportedException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowNotSupportedException<T>(string message)
public static T ThrowNotSupportedException<T>(string? message)
{
throw new NotSupportedException(message);
}
@ -752,7 +750,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="NotSupportedException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowNotSupportedException<T>(string message, Exception innerException)
public static T ThrowNotSupportedException<T>(string? message, Exception? innerException)
{
throw new NotSupportedException(message, innerException);
}
@ -765,7 +763,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ObjectDisposedException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowObjectDisposedException<T>(string objectName)
public static T ThrowObjectDisposedException<T>(string? objectName)
{
throw new ObjectDisposedException(objectName);
}
@ -779,7 +777,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ObjectDisposedException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowObjectDisposedException<T>(string objectName, Exception innerException)
public static T ThrowObjectDisposedException<T>(string? objectName, Exception? innerException)
{
throw new ObjectDisposedException(objectName, innerException);
}
@ -793,7 +791,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="ObjectDisposedException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowObjectDisposedException<T>(string objectName, string message)
public static T ThrowObjectDisposedException<T>(string? objectName, string? message)
{
throw new ObjectDisposedException(objectName, message);
}
@ -818,7 +816,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="OperationCanceledException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowOperationCanceledException<T>(string message)
public static T ThrowOperationCanceledException<T>(string? message)
{
throw new OperationCanceledException(message);
}
@ -832,7 +830,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="OperationCanceledException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowOperationCanceledException<T>(string message, Exception innerException)
public static T ThrowOperationCanceledException<T>(string? message, Exception? innerException)
{
throw new OperationCanceledException(message, innerException);
}
@ -859,7 +857,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="OperationCanceledException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowOperationCanceledException<T>(string message, CancellationToken token)
public static T ThrowOperationCanceledException<T>(string? message, CancellationToken token)
{
throw new OperationCanceledException(message, token);
}
@ -874,7 +872,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="OperationCanceledException">Thrown with the specified parameters.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowOperationCanceledException<T>(string message, Exception innerException, CancellationToken token)
public static T ThrowOperationCanceledException<T>(string? message, Exception? innerException, CancellationToken token)
{
throw new OperationCanceledException(message, innerException, token);
}
@ -899,7 +897,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="PlatformNotSupportedException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowPlatformNotSupportedException<T>(string message)
public static T ThrowPlatformNotSupportedException<T>(string? message)
{
throw new PlatformNotSupportedException(message);
}
@ -913,7 +911,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="PlatformNotSupportedException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowPlatformNotSupportedException<T>(string message, Exception innerException)
public static T ThrowPlatformNotSupportedException<T>(string? message, Exception? innerException)
{
throw new PlatformNotSupportedException(message, innerException);
}
@ -938,7 +936,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="SynchronizationLockException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowSynchronizationLockException<T>(string message)
public static T ThrowSynchronizationLockException<T>(string? message)
{
throw new SynchronizationLockException(message);
}
@ -952,7 +950,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="SynchronizationLockException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowSynchronizationLockException<T>(string message, Exception innerException)
public static T ThrowSynchronizationLockException<T>(string? message, Exception? innerException)
{
throw new SynchronizationLockException(message, innerException);
}
@ -977,7 +975,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="TimeoutException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowTimeoutException<T>(string message)
public static T ThrowTimeoutException<T>(string? message)
{
throw new TimeoutException(message);
}
@ -991,7 +989,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="TimeoutException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowTimeoutException<T>(string message, Exception innerException)
public static T ThrowTimeoutException<T>(string? message, Exception? innerException)
{
throw new TimeoutException(message, innerException);
}
@ -1016,7 +1014,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="UnauthorizedAccessException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowUnauthorizedAccessException<T>(string message)
public static T ThrowUnauthorizedAccessException<T>(string? message)
{
throw new UnauthorizedAccessException(message);
}
@ -1030,7 +1028,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="UnauthorizedAccessException">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowUnauthorizedAccessException<T>(string message, Exception innerException)
public static T ThrowUnauthorizedAccessException<T>(string? message, Exception? innerException)
{
throw new UnauthorizedAccessException(message, innerException);
}
@ -1069,7 +1067,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="Win32Exception">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowWin32Exception<T>(int error, string message)
public static T ThrowWin32Exception<T>(int error, string? message)
{
throw new Win32Exception(error, message);
}
@ -1082,7 +1080,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="Win32Exception">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowWin32Exception<T>(string message)
public static T ThrowWin32Exception<T>(string? message)
{
throw new Win32Exception(message);
}
@ -1096,7 +1094,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <exception cref="Win32Exception">Thrown with the specified parameter.</exception>
/// <returns>This method always throws, so it actually never returns a value.</returns>
[DoesNotReturn]
public static T ThrowWin32Exception<T>(string message, Exception innerException)
public static T ThrowWin32Exception<T>(string? message, Exception? innerException)
{
throw new Win32Exception(message, innerException);
}

Просмотреть файл

@ -11,8 +11,6 @@ using System.Runtime.InteropServices;
#endif
using System.Threading;
#nullable enable
namespace Microsoft.Toolkit.Diagnostics
{
/// <summary>
@ -36,7 +34,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="ArrayTypeMismatchException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowArrayTypeMismatchException(string message)
public static void ThrowArrayTypeMismatchException(string? message)
{
throw new ArrayTypeMismatchException(message);
}
@ -48,7 +46,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="ArrayTypeMismatchException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowArrayTypeMismatchException(string message, Exception innerException)
public static void ThrowArrayTypeMismatchException(string? message, Exception? innerException)
{
throw new ArrayTypeMismatchException(message, innerException);
}
@ -69,7 +67,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="ArgumentException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowArgumentException(string message)
public static void ThrowArgumentException(string? message)
{
throw new ArgumentException(message);
}
@ -81,7 +79,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="ArgumentException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowArgumentException(string message, Exception innerException)
public static void ThrowArgumentException(string? message, Exception? innerException)
{
throw new ArgumentException(message, innerException);
}
@ -93,7 +91,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="ArgumentException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowArgumentException(string name, string message)
public static void ThrowArgumentException(string? name, string? message)
{
throw new ArgumentException(message, name);
}
@ -106,7 +104,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="ArgumentException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowArgumentException(string name, string message, Exception innerException)
public static void ThrowArgumentException(string? name, string? message, Exception? innerException)
{
throw new ArgumentException(message, name, innerException);
}
@ -127,7 +125,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="name">The argument name.</param>
/// <exception cref="ArgumentNullException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowArgumentNullException(string name)
public static void ThrowArgumentNullException(string? name)
{
throw new ArgumentNullException(name);
}
@ -139,7 +137,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="ArgumentNullException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowArgumentNullException(string name, Exception innerException)
public static void ThrowArgumentNullException(string? name, Exception? innerException)
{
throw new ArgumentNullException(name, innerException);
}
@ -151,7 +149,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="ArgumentNullException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowArgumentNullException(string name, string message)
public static void ThrowArgumentNullException(string? name, string? message)
{
throw new ArgumentNullException(name, message);
}
@ -172,7 +170,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="name">The argument name.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowArgumentOutOfRangeException(string name)
public static void ThrowArgumentOutOfRangeException(string? name)
{
throw new ArgumentOutOfRangeException(name);
}
@ -184,7 +182,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowArgumentOutOfRangeException(string name, Exception innerException)
public static void ThrowArgumentOutOfRangeException(string? name, Exception? innerException)
{
throw new ArgumentOutOfRangeException(name, innerException);
}
@ -196,7 +194,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowArgumentOutOfRangeException(string name, string message)
public static void ThrowArgumentOutOfRangeException(string? name, string? message)
{
throw new ArgumentOutOfRangeException(name, message);
}
@ -209,7 +207,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowArgumentOutOfRangeException(string name, object value, string message)
public static void ThrowArgumentOutOfRangeException(string? name, object? value, string? message)
{
throw new ArgumentOutOfRangeException(name, value, message);
}
@ -231,7 +229,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="COMException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowCOMException(string message)
public static void ThrowCOMException(string? message)
{
throw new COMException(message);
}
@ -243,7 +241,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="COMException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowCOMException(string message, Exception innerException)
public static void ThrowCOMException(string? message, Exception? innerException)
{
throw new COMException(message, innerException);
}
@ -255,7 +253,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="error">The HRESULT of the errror to include.</param>
/// <exception cref="COMException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowCOMException(string message, int error)
public static void ThrowCOMException(string? message, int error)
{
throw new COMException(message, error);
}
@ -276,7 +274,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="ExternalException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowExternalException(string message)
public static void ThrowExternalException(string? message)
{
throw new ExternalException(message);
}
@ -288,7 +286,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="ExternalException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowExternalException(string message, Exception innerException)
public static void ThrowExternalException(string? message, Exception? innerException)
{
throw new ExternalException(message, innerException);
}
@ -300,7 +298,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="error">The HRESULT of the errror to include.</param>
/// <exception cref="ExternalException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowExternalException(string message, int error)
public static void ThrowExternalException(string? message, int error)
{
throw new ExternalException(message, error);
}
@ -322,7 +320,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="FormatException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowFormatException(string message)
public static void ThrowFormatException(string? message)
{
throw new FormatException(message);
}
@ -334,7 +332,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="FormatException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowFormatException(string message, Exception innerException)
public static void ThrowFormatException(string? message, Exception? innerException)
{
throw new FormatException(message, innerException);
}
@ -356,7 +354,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="InsufficientMemoryException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowInsufficientMemoryException(string message)
public static void ThrowInsufficientMemoryException(string? message)
{
throw new InsufficientMemoryException(message);
}
@ -368,7 +366,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="InsufficientMemoryException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowInsufficientMemoryException(string message, Exception innerException)
public static void ThrowInsufficientMemoryException(string? message, Exception? innerException)
{
throw new InsufficientMemoryException(message, innerException);
}
@ -390,7 +388,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="InvalidDataException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowInvalidDataException(string message)
public static void ThrowInvalidDataException(string? message)
{
throw new InvalidDataException(message);
}
@ -402,7 +400,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="InvalidDataException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowInvalidDataException(string message, Exception innerException)
public static void ThrowInvalidDataException(string? message, Exception? innerException)
{
throw new InvalidDataException(message, innerException);
}
@ -423,7 +421,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="InvalidOperationException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowInvalidOperationException(string message)
public static void ThrowInvalidOperationException(string? message)
{
throw new InvalidOperationException(message);
}
@ -435,7 +433,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="InvalidOperationException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowInvalidOperationException(string message, Exception innerException)
public static void ThrowInvalidOperationException(string? message, Exception? innerException)
{
throw new InvalidOperationException(message, innerException);
}
@ -456,7 +454,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="LockRecursionException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowLockRecursionException(string message)
public static void ThrowLockRecursionException(string? message)
{
throw new LockRecursionException(message);
}
@ -468,7 +466,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="LockRecursionException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowLockRecursionException(string message, Exception innerException)
public static void ThrowLockRecursionException(string? message, Exception? innerException)
{
throw new LockRecursionException(message, innerException);
}
@ -489,7 +487,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="MissingFieldException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowMissingFieldException(string message)
public static void ThrowMissingFieldException(string? message)
{
throw new MissingFieldException(message);
}
@ -501,7 +499,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="MissingFieldException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowMissingFieldException(string message, Exception innerException)
public static void ThrowMissingFieldException(string? message, Exception? innerException)
{
throw new MissingFieldException(message, innerException);
}
@ -514,7 +512,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="fieldName">The target field being retrieved.</param>
/// <exception cref="MissingFieldException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowMissingFieldException(string className, string fieldName)
public static void ThrowMissingFieldException(string? className, string? fieldName)
{
throw new MissingFieldException(className, fieldName);
}
@ -536,7 +534,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="MissingMemberException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowMissingMemberException(string message)
public static void ThrowMissingMemberException(string? message)
{
throw new MissingMemberException(message);
}
@ -548,7 +546,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="MissingMemberException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowMissingMemberException(string message, Exception innerException)
public static void ThrowMissingMemberException(string? message, Exception? innerException)
{
throw new MissingMemberException(message, innerException);
}
@ -561,7 +559,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="memberName">The target member being retrieved.</param>
/// <exception cref="MissingMemberException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowMissingMemberException(string className, string memberName)
public static void ThrowMissingMemberException(string? className, string? memberName)
{
throw new MissingMemberException(className, memberName);
}
@ -583,7 +581,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="MissingMethodException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowMissingMethodException(string message)
public static void ThrowMissingMethodException(string? message)
{
throw new MissingMethodException(message);
}
@ -595,7 +593,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="MissingMethodException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowMissingMethodException(string message, Exception innerException)
public static void ThrowMissingMethodException(string? message, Exception? innerException)
{
throw new MissingMethodException(message, innerException);
}
@ -608,7 +606,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="methodName">The target method being retrieved.</param>
/// <exception cref="MissingMethodException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowMissingMethodException(string className, string methodName)
public static void ThrowMissingMethodException(string? className, string? methodName)
{
throw new MissingMethodException(className, methodName);
}
@ -630,7 +628,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="NotSupportedException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowNotSupportedException(string message)
public static void ThrowNotSupportedException(string? message)
{
throw new NotSupportedException(message);
}
@ -642,7 +640,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="NotSupportedException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowNotSupportedException(string message, Exception innerException)
public static void ThrowNotSupportedException(string? message, Exception? innerException)
{
throw new NotSupportedException(message, innerException);
}
@ -653,7 +651,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="objectName">The name of the disposed object.</param>
/// <exception cref="ObjectDisposedException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowObjectDisposedException(string objectName)
public static void ThrowObjectDisposedException(string? objectName)
{
throw new ObjectDisposedException(objectName);
}
@ -665,7 +663,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="ObjectDisposedException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowObjectDisposedException(string objectName, Exception innerException)
public static void ThrowObjectDisposedException(string? objectName, Exception? innerException)
{
throw new ObjectDisposedException(objectName, innerException);
}
@ -677,7 +675,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="ObjectDisposedException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowObjectDisposedException(string objectName, string message)
public static void ThrowObjectDisposedException(string? objectName, string? message)
{
throw new ObjectDisposedException(objectName, message);
}
@ -698,7 +696,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="OperationCanceledException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowOperationCanceledException(string message)
public static void ThrowOperationCanceledException(string? message)
{
throw new OperationCanceledException(message);
}
@ -710,7 +708,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="OperationCanceledException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowOperationCanceledException(string message, Exception innerException)
public static void ThrowOperationCanceledException(string? message, Exception? innerException)
{
throw new OperationCanceledException(message, innerException);
}
@ -733,7 +731,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="token">The <see cref="CancellationToken"/> in use.</param>
/// <exception cref="OperationCanceledException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowOperationCanceledException(string message, CancellationToken token)
public static void ThrowOperationCanceledException(string? message, CancellationToken token)
{
throw new OperationCanceledException(message, token);
}
@ -746,7 +744,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="token">The <see cref="CancellationToken"/> in use.</param>
/// <exception cref="OperationCanceledException">Thrown with the specified parameters.</exception>
[DoesNotReturn]
public static void ThrowOperationCanceledException(string message, Exception innerException, CancellationToken token)
public static void ThrowOperationCanceledException(string? message, Exception? innerException, CancellationToken token)
{
throw new OperationCanceledException(message, innerException, token);
}
@ -767,7 +765,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="PlatformNotSupportedException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowPlatformNotSupportedException(string message)
public static void ThrowPlatformNotSupportedException(string? message)
{
throw new PlatformNotSupportedException(message);
}
@ -779,7 +777,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="PlatformNotSupportedException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowPlatformNotSupportedException(string message, Exception innerException)
public static void ThrowPlatformNotSupportedException(string? message, Exception? innerException)
{
throw new PlatformNotSupportedException(message, innerException);
}
@ -800,7 +798,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="SynchronizationLockException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowSynchronizationLockException(string message)
public static void ThrowSynchronizationLockException(string? message)
{
throw new SynchronizationLockException(message);
}
@ -812,7 +810,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="SynchronizationLockException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowSynchronizationLockException(string message, Exception innerException)
public static void ThrowSynchronizationLockException(string? message, Exception? innerException)
{
throw new SynchronizationLockException(message, innerException);
}
@ -833,7 +831,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="TimeoutException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowTimeoutException(string message)
public static void ThrowTimeoutException(string? message)
{
throw new TimeoutException(message);
}
@ -845,7 +843,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="TimeoutException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowTimeoutException(string message, Exception innerException)
public static void ThrowTimeoutException(string? message, Exception? innerException)
{
throw new TimeoutException(message, innerException);
}
@ -866,7 +864,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="UnauthorizedAccessException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowUnauthorizedAccessException(string message)
public static void ThrowUnauthorizedAccessException(string? message)
{
throw new UnauthorizedAccessException(message);
}
@ -878,7 +876,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="UnauthorizedAccessException">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowUnauthorizedAccessException(string message, Exception innerException)
public static void ThrowUnauthorizedAccessException(string? message, Exception? innerException)
{
throw new UnauthorizedAccessException(message, innerException);
}
@ -911,7 +909,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="Win32Exception">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowWin32Exception(int error, string message)
public static void ThrowWin32Exception(int error, string? message)
{
throw new Win32Exception(error, message);
}
@ -922,7 +920,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="message">The message to include in the exception.</param>
/// <exception cref="Win32Exception">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowWin32Exception(string message)
public static void ThrowWin32Exception(string? message)
{
throw new Win32Exception(message);
}
@ -934,7 +932,7 @@ namespace Microsoft.Toolkit.Diagnostics
/// <param name="innerException">The inner <see cref="Exception"/> to include.</param>
/// <exception cref="Win32Exception">Thrown with the specified parameter.</exception>
[DoesNotReturn]
public static void ThrowWin32Exception(string message, Exception innerException)
public static void ThrowWin32Exception(string? message, Exception? innerException)
{
throw new Win32Exception(message, innerException);
}

Просмотреть файл

@ -23,7 +23,7 @@ namespace Microsoft.Toolkit.Extensions
/// <param name="rectarray">The source array.</param>
/// <param name="column">Column record to retrieve, 0-based index.</param>
/// <returns>Yielded enumerable of column elements for given column, and default values for smaller inner arrays.</returns>
public static IEnumerable<T> GetColumn<T>(this T[][] rectarray, int column)
public static IEnumerable<T?> GetColumn<T>(this T?[][] rectarray, int column)
{
if (column < 0 || column >= rectarray.Max(array => array.Length))
{
@ -49,10 +49,10 @@ namespace Microsoft.Toolkit.Extensions
/// <typeparam name="T">The element type of the array.</typeparam>
/// <param name="array">The source array.</param>
/// <returns>The <see cref="string"/> representation of the array.</returns>
public static string ToArrayString<T>(this T[] array)
public static string ToArrayString<T>(this T?[] array)
{
// The returned string will be in the following format:
// [1, 2, 3]
// [1, 2, 3]
StringBuilder builder = new StringBuilder();
builder.Append('[');
@ -64,7 +64,7 @@ namespace Microsoft.Toolkit.Extensions
builder.Append(",\t");
}
builder.Append(array[i].ToString());
builder.Append(array[i]?.ToString());
}
builder.Append(']');
@ -78,7 +78,7 @@ namespace Microsoft.Toolkit.Extensions
/// <typeparam name="T">The element type of the array.</typeparam>
/// <param name="mdarray">The source array.</param>
/// <returns>String representation of the array.</returns>
public static string ToArrayString<T>(this T[][] mdarray)
public static string ToArrayString<T>(this T?[][] mdarray)
{
// The returned string uses the same format as the overload for 2D arrays
StringBuilder builder = new StringBuilder();
@ -96,7 +96,7 @@ namespace Microsoft.Toolkit.Extensions
builder.Append('[');
T[] row = mdarray[i];
T?[] row = mdarray[i];
for (int j = 0; j < row.Length; j++)
{
@ -105,7 +105,7 @@ namespace Microsoft.Toolkit.Extensions
builder.Append(",\t");
}
builder.Append(row[j].ToString());
builder.Append(row[j]?.ToString());
}
builder.Append(']');
@ -122,7 +122,7 @@ namespace Microsoft.Toolkit.Extensions
/// <typeparam name="T">The element type of the array.</typeparam>
/// <param name="array">The source array.</param>
/// <returns>The <see cref="string"/> representation of the array.</returns>
public static string ToArrayString<T>(this T[,] array)
public static string ToArrayString<T>(this T?[,] array)
{
// The returned string will be in the following format:
// [[1, 2, 3],
@ -154,7 +154,7 @@ namespace Microsoft.Toolkit.Extensions
builder.Append(",\t");
}
builder.Append(array[i, j].ToString());
builder.Append(array[i, j]?.ToString());
}
builder.Append(']');

Просмотреть файл

@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net;
using System.Text.RegularExpressions;
@ -62,15 +62,20 @@ namespace Microsoft.Toolkit.Extensions
/// </summary>
/// <param name="str">The string to test.</param>
/// <returns><c>true</c> for a valid decimal number; otherwise, <c>false</c>.</returns>
public static bool IsDecimal(this string str)
=> decimal.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out _);
public static bool IsDecimal([NotNullWhen(true)] this string? str)
{
return decimal.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out _);
}
/// <summary>
/// Determines whether a string is a valid integer.
/// </summary>
/// <param name="str">The string to test.</param>
/// <returns><c>true</c> for a valid integer; otherwise, <c>false</c>.</returns>
public static bool IsNumeric(this string str) => int.TryParse(str, out _);
public static bool IsNumeric([NotNullWhen(true)] this string? str)
{
return int.TryParse(str, out _);
}
/// <summary>
/// Determines whether a string is a valid phone number.
@ -91,9 +96,10 @@ namespace Microsoft.Toolkit.Extensions
/// </summary>
/// <param name="htmlText">HTML string.</param>
/// <returns>Decoded HTML string.</returns>
public static string DecodeHtml(this string htmlText)
[return: NotNullIfNotNull("htmlText")]
public static string? DecodeHtml(this string? htmlText)
{
if (htmlText == null)
if (htmlText is null)
{
return null;
}
@ -131,7 +137,7 @@ namespace Microsoft.Toolkit.Extensions
/// <param name="value">The string to be truncated.</param>
/// <param name="length">The maximum length.</param>
/// <returns>Truncated string.</returns>
public static string Truncate(this string value, int length) => Truncate(value, length, false);
public static string Truncate(this string? value, int length) => Truncate(value, length, false);
/// <summary>
/// Provide better linking for resourced strings.
@ -148,11 +154,12 @@ namespace Microsoft.Toolkit.Extensions
/// <param name="length">The maximum length.</param>
/// <param name="ellipsis"><c>true</c> to add ellipsis to the truncated text; otherwise, <c>false</c>.</param>
/// <returns>Truncated string.</returns>
public static string Truncate(this string value, int length, bool ellipsis)
public static string Truncate(this string? value, int length, bool ellipsis)
{
if (!string.IsNullOrEmpty(value))
{
value = value.Trim();
value = value!.Trim();
if (value.Length > length)
{
if (ellipsis)

Просмотреть файл

@ -2,14 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
#nullable enable
namespace Microsoft.Toolkit.Extensions
{
/// <summary>
@ -69,8 +66,7 @@ namespace Microsoft.Toolkit.Extensions
/// <remarks>This method does not block if <paramref name="task"/> has not completed yet.</remarks>
[Pure]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[return: MaybeNull]
public static T GetResultOrDefault<T>(this Task<T> task)
public static T? GetResultOrDefault<T>(this Task<T?> task)
{
#if NETSTANDARD2_1
return task.IsCompletedSuccessfully ? task.Result : default;

Просмотреть файл

@ -11,8 +11,6 @@ using System.Reflection;
#endif
using System.Runtime.CompilerServices;
#nullable enable
namespace Microsoft.Toolkit.Extensions
{
/// <summary>

Просмотреть файл

@ -15,7 +15,7 @@ namespace Microsoft.Toolkit.Extensions
public static class ValueTypeExtensions
{
/// <summary>
/// Gets the table of hex characters (doesn't allocate, maps to .text section, see <see href="https://github.com/dotnet/roslyn/pull/24621"/>)
/// Gets the table of hex characters (doesn't allocate, maps to .text section, see <see href="https://github.com/dotnet/roslyn/pull/24621"/>).
/// </summary>
private static ReadOnlySpan<byte> HexCharactersTable => new[]
{
@ -43,7 +43,7 @@ namespace Microsoft.Toolkit.Extensions
/// </code>
/// </remarks>
[Pure]
[MethodImpl(MethodImplOptions.NoInlining)]
[SkipLocalsInit]
public static unsafe string ToHexString<T>(this T value)
where T : unmanaged
{
@ -55,12 +55,11 @@ namespace Microsoft.Toolkit.Extensions
p[0] = '0';
p[1] = 'x';
ref byte r0 = ref Unsafe.As<T, byte>(ref value);
ref byte rh = ref MemoryMarshal.GetReference(HexCharactersTable);
for (int i = 0, j = bufferSize - 2; i < sizeOfT; i++, j -= 2)
{
byte b = Unsafe.Add(ref r0, i);
byte b = ((byte*)&value)[i];
int
low = b & 0x0F,
high = (b & 0xF0) >> 4;

Просмотреть файл

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard1.4;netstandard2.0;netstandard2.1</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<TargetFrameworks>netstandard1.4;netstandard2.0;netstandard2.1;net5.0</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Nullable>enable</Nullable>
<Title>Windows Community Toolkit .NET Standard</Title>
<Description>
This package includes .NET Standard code only helpers such as:
@ -12,23 +13,39 @@
</Description>
<PackageTags>UWP Toolkit Windows IncrementalLoadingCollection String Array extensions helpers</PackageTags>
</PropertyGroup>
<Choose>
<When Condition=" '$(TargetFramework)' == 'netstandard1.4' ">
<ItemGroup>
<!-- .NET Standard 1.4 doesn't have the Span<T> type, ValueTuple or the [Pure] attribute -->
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.4' ">
<PackageReference Include="System.Diagnostics.Contracts" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>
<!-- .NET Standard 1.4 doesn't have the Span<T> type, ValueTuple or the [Pure] attribute -->
<PackageReference Include="System.Diagnostics.Contracts" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>
</When>
<When Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<ItemGroup>
<!-- .NET Standard 2.0 doesn't have the Span<T> type -->
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>
<!-- .NET Standard 2.0 doesn't have the Span<T> type -->
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>
</When>
<When Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
<PropertyGroup>
<DefineConstants>NETSTANDARD2_1_OR_GREATER</DefineConstants>
</PropertyGroup>
<ItemGroup>
<!-- .NET Standard 2.1 doesn't have the Unsafe type -->
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.1' ">
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.1" />
</ItemGroup>
<!-- .NET Standard 2.1 doesn't have the Unsafe type -->
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
</ItemGroup>
</When>
<When Condition=" '$(TargetFramework)' == 'net5.0' ">
<PropertyGroup>
<DefineConstants>NETSTANDARD2_1_OR_GREATER</DefineConstants>
</PropertyGroup>
</When>
</Choose>
<ItemGroup>
<None Update="Diagnostics\Generated\Guard.Comparable.Numeric.tt">

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
<LangVersion>8.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<IsPackable>false</IsPackable>

Просмотреть файл

@ -188,28 +188,43 @@ namespace UnitTests.HighPerformance.Buffers
[TestMethod]
public void Test_ArrayPoolBufferWriterOfT_AsStream()
{
const int GuidSize = 16;
var writer = new ArrayPoolBufferWriter<byte>();
var guid = Guid.NewGuid();
Span<byte> data = Guid.NewGuid().ToByteArray();
// Here we first get a stream with the extension targeting ArrayPoolBufferWriter<T>.
// This will wrap it into a custom internal stream type and produce a write-only
// stream that essentially mirrors the IBufferWriter<T> functionality as a stream.
using (Stream writeStream = writer.AsStream())
{
writeStream.Write(guid);
}
data.CopyTo(writer.GetSpan(data.Length));
Assert.AreEqual(writer.WrittenCount, GuidSize);
writer.Advance(data.Length);
// Here we get a readable stream instead, and read from it to ensure
// the previous data was written correctly from the writeable stream.
using (Stream stream = writer.WrittenMemory.AsStream())
{
Assert.AreEqual(stream.Length, GuidSize);
Assert.AreEqual(writer.WrittenCount, data.Length);
byte[] result = new byte[GuidSize];
Stream stream = writer.AsStream();
stream.Read(result, 0, result.Length);
Assert.AreEqual(stream.Length, data.Length);
// Read the guid data and ensure it matches our initial guid
Assert.IsTrue(new Guid(result).Equals(guid));
}
byte[] result = new byte[16];
// Do a dummy write just to ensure the writer isn't disposed here.
// This is because we got a stream from a memory, not a memory owner.
writer.Write((byte)42);
writer.Advance(1);
stream.Read(result, 0, result.Length);
Assert.IsTrue(data.SequenceEqual(result));
stream.Dispose();
writer.Dispose();
// Now check that the writer is actually disposed instead
Assert.ThrowsException<ObjectDisposedException>(() => writer.Capacity);
}
}

Просмотреть файл

@ -436,7 +436,7 @@ namespace UnitTests.HighPerformance.Extensions
Assert.ThrowsException<ArgumentOutOfRangeException>(() => array.GetColumn(0).ToArray());
}
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
[TestCategory("ArrayExtensions")]
[TestMethod]
public void Test_ArrayExtensions_2D_AsSpan_Empty()

Просмотреть файл

@ -63,6 +63,7 @@ namespace UnitTests.HighPerformance.Helpers
TestForType<char>();
}
#if NETCOREAPP3_1 || NET5_0
[TestCategory("HashCodeOfT")]
[TestMethod]
public void Test_HashCodeOfT_ManagedType_TestRepeat()
@ -88,6 +89,7 @@ namespace UnitTests.HighPerformance.Helpers
Assert.AreEqual(hash1, hash2, $"Failed {typeof(string)} test with count {count}: got {hash1} and then {hash2}");
}
}
#endif
/// <summary>
/// Performs a test for a specified type.

Просмотреть файл

@ -40,7 +40,7 @@ namespace UnitTests.HighPerformance.Helpers
}
}
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
[TestCategory("ParallelHelper")]
[TestMethod]
[ExpectedException(typeof(ArgumentException))]

Просмотреть файл

@ -51,7 +51,7 @@ namespace UnitTests.HighPerformance.Helpers
}
}
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
[TestCategory("ParallelHelper")]
[TestMethod]
[ExpectedException(typeof(ArgumentException))]

Просмотреть файл

@ -0,0 +1,161 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Toolkit.HighPerformance.Buffers;
using Microsoft.Toolkit.HighPerformance.Extensions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTests.HighPerformance.Streams
{
[TestClass]
public class Test_IBufferWriterStream
{
[TestCategory("IBufferWriterStream")]
[TestMethod]
public void Test_IBufferWriterStream_Lifecycle()
{
ArrayPoolBufferWriter<byte> writer = new ArrayPoolBufferWriter<byte>();
// Get a stream from a buffer writer aand validate that it can only be written to.
// This is to mirror the same functionality as the IBufferWriter<T> interface.
Stream stream = ((IBufferWriter<byte>)writer).AsStream();
Assert.IsFalse(stream.CanRead);
Assert.IsFalse(stream.CanSeek);
Assert.IsTrue(stream.CanWrite);
Assert.ThrowsException<NotSupportedException>(() => stream.Length);
Assert.ThrowsException<NotSupportedException>(() => stream.Position);
// Dispose the stream and check that no operation is now allowed
stream.Dispose();
Assert.IsFalse(stream.CanRead);
Assert.IsFalse(stream.CanSeek);
Assert.IsFalse(stream.CanWrite);
Assert.ThrowsException<NotSupportedException>(() => stream.Length);
Assert.ThrowsException<NotSupportedException>(() => stream.Position);
}
[TestCategory("IBufferWriterStream")]
[TestMethod]
public void Test_IBufferWriterStream_Write_Array()
{
ArrayPoolBufferWriter<byte> writer = new ArrayPoolBufferWriter<byte>();
Stream stream = ((IBufferWriter<byte>)writer).AsStream();
byte[] data = Test_MemoryStream.CreateRandomData(64);
// Write random data to the stream wrapping the buffer writer, and validate
// that the state of the writer is consistent, and the written content matches.
stream.Write(data, 0, data.Length);
Assert.AreEqual(writer.WrittenCount, data.Length);
Assert.IsTrue(writer.WrittenSpan.SequenceEqual(data));
// A few tests with invalid inputs (null buffers, invalid indices, etc.)
Assert.ThrowsException<ArgumentNullException>(() => stream.Write(null, 0, 10));
Assert.ThrowsException<ArgumentOutOfRangeException>(() => stream.Write(data, -1, 10));
Assert.ThrowsException<ArgumentException>(() => stream.Write(data, 200, 10));
Assert.ThrowsException<ArgumentOutOfRangeException>(() => stream.Write(data, 0, -24));
Assert.ThrowsException<ArgumentException>(() => stream.Write(data, 0, 200));
stream.Dispose();
Assert.ThrowsException<ObjectDisposedException>(() => stream.Write(data, 0, data.Length));
}
[TestCategory("IBufferWriterStream")]
[TestMethod]
public async Task Test_IBufferWriterStream_WriteAsync_Array()
{
ArrayPoolBufferWriter<byte> writer = new ArrayPoolBufferWriter<byte>();
Stream stream = ((IBufferWriter<byte>)writer).AsStream();
byte[] data = Test_MemoryStream.CreateRandomData(64);
// Same test as above, but using an asynchronous write instead
await stream.WriteAsync(data, 0, data.Length);
Assert.AreEqual(writer.WrittenCount, data.Length);
Assert.IsTrue(writer.WrittenSpan.SequenceEqual(data));
await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => stream.WriteAsync(null, 0, 10));
await Assert.ThrowsExceptionAsync<ArgumentOutOfRangeException>(() => stream.WriteAsync(data, -1, 10));
await Assert.ThrowsExceptionAsync<ArgumentException>(() => stream.WriteAsync(data, 200, 10));
await Assert.ThrowsExceptionAsync<ArgumentOutOfRangeException>(() => stream.WriteAsync(data, 0, -24));
await Assert.ThrowsExceptionAsync<ArgumentException>(() => stream.WriteAsync(data, 0, 200));
stream.Dispose();
await Assert.ThrowsExceptionAsync<ObjectDisposedException>(() => stream.WriteAsync(data, 0, data.Length));
}
[TestCategory("IBufferWriterStream")]
[TestMethod]
[SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1500", Justification = "Array initialization")]
public void Test_IBufferWriterStream_WriteByte()
{
ArrayPoolBufferWriter<byte> writer = new ArrayPoolBufferWriter<byte>();
Stream stream = ((IBufferWriter<byte>)writer).AsStream();
ReadOnlySpan<byte> data = stackalloc byte[] { 1, 128, 255, 32 };
foreach (var item in data.Enumerate())
{
// Since we're enumerating, we can also double check the current written count
// at each iteration, to ensure the writes are done correctly every time.
Assert.AreEqual(writer.WrittenCount, item.Index);
// Write a number of bytes one by one to test this API as well
stream.WriteByte(item.Value);
}
// Validate the final written length and actual data
Assert.AreEqual(writer.WrittenCount, data.Length);
Assert.IsTrue(data.SequenceEqual(writer.WrittenSpan));
Assert.ThrowsException<NotSupportedException>(() => stream.ReadByte());
}
[TestCategory("IBufferWriterStream")]
[TestMethod]
public void Test_IBufferWriterStream_Write_Span()
{
ArrayPoolBufferWriter<byte> writer = new ArrayPoolBufferWriter<byte>();
Stream stream = ((IBufferWriter<byte>)writer).AsStream();
Memory<byte> data = Test_MemoryStream.CreateRandomData(64);
// This will use the extension when on .NET Standard 2.0,
// as the Stream class doesn't have Spam<T> or Memory<T>
// public APIs there. This is the case eg. on UWP as well.
stream.Write(data.Span);
Assert.AreEqual(writer.WrittenCount, data.Length);
Assert.IsTrue(data.Span.SequenceEqual(writer.WrittenSpan));
}
[TestCategory("IBufferWriterStream")]
[TestMethod]
public async Task Test_IBufferWriterStream_WriteAsync_Memory()
{
ArrayPoolBufferWriter<byte> writer = new ArrayPoolBufferWriter<byte>();
Stream stream = ((IBufferWriter<byte>)writer).AsStream();
Memory<byte> data = Test_MemoryStream.CreateRandomData(64);
// Same as the other asynchronous test above, but writing from a Memory<T>
await stream.WriteAsync(data);
Assert.AreEqual(writer.WrittenCount, data.Length);
Assert.IsTrue(data.Span.SequenceEqual(writer.WrittenSpan));
}
}
}

Просмотреть файл

@ -272,7 +272,7 @@ namespace UnitTests.HighPerformance.Streams
/// <param name="count">The number of array items to create.</param>
/// <returns>The returned random array.</returns>
[Pure]
private static byte[] CreateRandomData(int count)
internal static byte[] CreateRandomData(int count)
{
var random = new Random(DateTime.Now.Ticks.GetHashCode());

Просмотреть файл

@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
using System;
using System.Diagnostics.CodeAnalysis;

Просмотреть файл

@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if NETCOREAPP3_1
#if NETCOREAPP3_1 || NET5_0
using System;
using System.Diagnostics.CodeAnalysis;

Просмотреть файл

@ -47,6 +47,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Memory\Test_Memory2D{T}.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Memory\Test_Span2D{T}.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Streams\Test_IMemoryOwnerStream.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Streams\Test_IBufferWriterStream.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Streams\Test_MemoryStream.ThrowExceptions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Streams\Test_MemoryStream.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Test_Box{T}.cs" />

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<LangVersion>8.0</LangVersion>
</PropertyGroup>

Просмотреть файл

@ -4,6 +4,7 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Toolkit.Uwp.Extensions;
using Microsoft.Toolkit.Uwp.Helpers;
using Microsoft.Toolkit.Uwp.Input.GazeInteraction;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@ -21,7 +22,7 @@ namespace UnitTests.XamlIslands.UWPApp
[TestInitialize]
public async Task Init()
{
await App.Dispatcher.ExecuteOnUIThreadAsync(() =>
await App.Dispatcher.EnqueueAsync(() =>
{
var xamlItemsPanelTemplate = @"<Grid xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
@ -65,7 +66,7 @@ namespace UnitTests.XamlIslands.UWPApp
[TestCleanup]
public async Task Cleanup()
{
await App.Dispatcher.ExecuteOnUIThreadAsync(() =>
await App.Dispatcher.EnqueueAsync(() =>
{
GazeInput.SetInteraction(_grid, Interaction.Disabled);
});
@ -76,7 +77,7 @@ namespace UnitTests.XamlIslands.UWPApp
[Ignore]
public async Task Gaze_DoesNotCrashOnIslands()
{
await App.Dispatcher.ExecuteOnUIThreadAsync(async () =>
await App.Dispatcher.EnqueueAsync(async () =>
{
await Task.Delay(10000);

Просмотреть файл

@ -43,11 +43,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Toolkit.Uwp.Notif
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests.Notifications.NetCore", "UnitTests\UnitTests.Notifications.NetCore\UnitTests.Notifications.NetCore.csproj", "{94994424-5F60-4CD8-ABA2-101779066208}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests.Notifications.WinRT", "UnitTests\UnitTests.Notifications.WinRT\UnitTests.Notifications.WinRT.csproj", "{EFA96B3C-857E-4659-B942-6BEF7719F4CA}"
ProjectSection(ProjectDependencies) = postProject
{97EE849B-403C-490E-80ED-D19D7CC153FD} = {97EE849B-403C-490E-80ED-D19D7CC153FD}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{CFA75BE0-5A44-45DE-8114-426A605B062B}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
@ -148,7 +143,6 @@ Global
UnitTests\UnitTests.Shared\UnitTests.Shared.projitems*{a139968e-ad78-4e8c-93b8-9a5523bcac89}*SharedItemsImports = 4
UnitTests\UnitTests.Notifications.Shared\UnitTests.Notifications.Shared.projitems*{bab1caf4-c400-4a7f-a987-c576de63cffd}*SharedItemsImports = 4
UnitTests\UnitTests.HighPerformance.Shared\UnitTests.HighPerformance.Shared.projitems*{d9bdbc68-3d0a-47fc-9c88-0bf769101644}*SharedItemsImports = 5
UnitTests\UnitTests.Notifications.Shared\UnitTests.Notifications.Shared.projitems*{efa96b3c-857e-4659-b942-6bef7719f4ca}*SharedItemsImports = 4
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -486,34 +480,6 @@ Global
{94994424-5F60-4CD8-ABA2-101779066208}.Release|x64.Build.0 = Release|Any CPU
{94994424-5F60-4CD8-ABA2-101779066208}.Release|x86.ActiveCfg = Release|Any CPU
{94994424-5F60-4CD8-ABA2-101779066208}.Release|x86.Build.0 = Release|Any CPU
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|Any CPU.ActiveCfg = Debug|x86
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|Any CPU.Build.0 = Debug|x86
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|ARM.ActiveCfg = Debug|ARM
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|ARM.Build.0 = Debug|ARM
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|ARM.Deploy.0 = Debug|ARM
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|ARM64.ActiveCfg = Debug|ARM64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|ARM64.Build.0 = Debug|ARM64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|ARM64.Deploy.0 = Debug|ARM64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|x64.ActiveCfg = Debug|x64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|x64.Build.0 = Debug|x64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|x64.Deploy.0 = Debug|x64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|x86.ActiveCfg = Debug|x86
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|x86.Build.0 = Debug|x86
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Debug|x86.Deploy.0 = Debug|x86
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|Any CPU.ActiveCfg = Release|x86
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|Any CPU.Build.0 = Release|x86
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|ARM.ActiveCfg = Release|ARM
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|ARM.Build.0 = Release|ARM
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|ARM.Deploy.0 = Release|ARM
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|ARM64.ActiveCfg = Release|ARM64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|ARM64.Build.0 = Release|ARM64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|ARM64.Deploy.0 = Release|ARM64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|x64.ActiveCfg = Release|x64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|x64.Build.0 = Release|x64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|x64.Deploy.0 = Release|x64
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|x86.ActiveCfg = Release|x86
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|x86.Build.0 = Release|x86
{EFA96B3C-857E-4659-B942-6BEF7719F4CA}.Release|x86.Deploy.0 = Release|x86
{7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug|Any CPU.ActiveCfg = Debug|x86
{7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug|Any CPU.Build.0 = Debug|x86
{7AEFC959-ED7C-4D96-9E92-72609B40FBE0}.Debug|ARM.ActiveCfg = Debug|x86
@ -1026,7 +992,6 @@ Global
{BAB1CAF4-C400-4A7F-A987-C576DE63CFFD} = {9333C63A-F64F-4797-82B3-017422668A5D}
{1AE2CB5C-58A0-4F12-8E6F-2CD4AAADB34C} = {9AD30620-667D-433C-9961-8D885EE7B762}
{94994424-5F60-4CD8-ABA2-101779066208} = {9333C63A-F64F-4797-82B3-017422668A5D}
{EFA96B3C-857E-4659-B942-6BEF7719F4CA} = {9333C63A-F64F-4797-82B3-017422668A5D}
{7AEFC959-ED7C-4D96-9E92-72609B40FBE0} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC}
{6BD0BA4A-DE6D-3E87-8F83-63518C31ECD1} = {F1AFFFA7-28FE-4770-BA48-10D76F3E59BC}
{A122EA02-4DE7-413D-BFBF-AF7DFC668DD6} = {B30036C4-D514-4E5B-A323-587A061772CE}