diff --git a/Microsoft.Toolkit/Attributes/DoesNotReturnAttribute.cs b/Microsoft.Toolkit.Diagnostics/Attributes/DoesNotReturnAttribute.cs similarity index 100% rename from Microsoft.Toolkit/Attributes/DoesNotReturnAttribute.cs rename to Microsoft.Toolkit.Diagnostics/Attributes/DoesNotReturnAttribute.cs diff --git a/Microsoft.Toolkit/Attributes/DoesNotReturnIfAttribute.cs b/Microsoft.Toolkit.Diagnostics/Attributes/DoesNotReturnIfAttribute.cs similarity index 100% rename from Microsoft.Toolkit/Attributes/DoesNotReturnIfAttribute.cs rename to Microsoft.Toolkit.Diagnostics/Attributes/DoesNotReturnIfAttribute.cs diff --git a/Microsoft.Toolkit/Attributes/NotNullAttribute.cs b/Microsoft.Toolkit.Diagnostics/Attributes/NotNullAttribute.cs similarity index 100% rename from Microsoft.Toolkit/Attributes/NotNullAttribute.cs rename to Microsoft.Toolkit.Diagnostics/Attributes/NotNullAttribute.cs diff --git a/Microsoft.Toolkit/Attributes/SkipLocalsInitAttribute.cs b/Microsoft.Toolkit.Diagnostics/Attributes/SkipLocalsInitAttribute.cs similarity index 100% rename from Microsoft.Toolkit/Attributes/SkipLocalsInitAttribute.cs rename to Microsoft.Toolkit.Diagnostics/Attributes/SkipLocalsInitAttribute.cs diff --git a/Microsoft.Toolkit/Extensions/TypeExtensions.cs b/Microsoft.Toolkit.Diagnostics/Extensions/TypeExtensions.cs similarity index 100% rename from Microsoft.Toolkit/Extensions/TypeExtensions.cs rename to Microsoft.Toolkit.Diagnostics/Extensions/TypeExtensions.cs diff --git a/Microsoft.Toolkit/Extensions/ValueTypeExtensions.cs b/Microsoft.Toolkit.Diagnostics/Extensions/ValueTypeExtensions.cs similarity index 100% rename from Microsoft.Toolkit/Extensions/ValueTypeExtensions.cs rename to Microsoft.Toolkit.Diagnostics/Extensions/ValueTypeExtensions.cs diff --git a/Microsoft.Toolkit/Diagnostics/Generated/Guard.Collection.g.cs b/Microsoft.Toolkit.Diagnostics/Generated/Guard.Collection.g.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Generated/Guard.Collection.g.cs rename to Microsoft.Toolkit.Diagnostics/Generated/Guard.Collection.g.cs diff --git a/Microsoft.Toolkit/Diagnostics/Generated/Guard.Collection.tt b/Microsoft.Toolkit.Diagnostics/Generated/Guard.Collection.tt similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Generated/Guard.Collection.tt rename to Microsoft.Toolkit.Diagnostics/Generated/Guard.Collection.tt diff --git a/Microsoft.Toolkit/Diagnostics/Generated/Guard.Comparable.Numeric.g.cs b/Microsoft.Toolkit.Diagnostics/Generated/Guard.Comparable.Numeric.g.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Generated/Guard.Comparable.Numeric.g.cs rename to Microsoft.Toolkit.Diagnostics/Generated/Guard.Comparable.Numeric.g.cs diff --git a/Microsoft.Toolkit/Diagnostics/Generated/Guard.Comparable.Numeric.tt b/Microsoft.Toolkit.Diagnostics/Generated/Guard.Comparable.Numeric.tt similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Generated/Guard.Comparable.Numeric.tt rename to Microsoft.Toolkit.Diagnostics/Generated/Guard.Comparable.Numeric.tt diff --git a/Microsoft.Toolkit/Diagnostics/Generated/Guard.md b/Microsoft.Toolkit.Diagnostics/Generated/Guard.md similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Generated/Guard.md rename to Microsoft.Toolkit.Diagnostics/Generated/Guard.md diff --git a/Microsoft.Toolkit/Diagnostics/Generated/ThrowHelper.Collection.g.cs b/Microsoft.Toolkit.Diagnostics/Generated/ThrowHelper.Collection.g.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Generated/ThrowHelper.Collection.g.cs rename to Microsoft.Toolkit.Diagnostics/Generated/ThrowHelper.Collection.g.cs diff --git a/Microsoft.Toolkit/Diagnostics/Generated/ThrowHelper.Collection.tt b/Microsoft.Toolkit.Diagnostics/Generated/ThrowHelper.Collection.tt similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Generated/ThrowHelper.Collection.tt rename to Microsoft.Toolkit.Diagnostics/Generated/ThrowHelper.Collection.tt diff --git a/Microsoft.Toolkit/Diagnostics/Generated/TypeInfo.ttinclude b/Microsoft.Toolkit.Diagnostics/Generated/TypeInfo.ttinclude similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Generated/TypeInfo.ttinclude rename to Microsoft.Toolkit.Diagnostics/Generated/TypeInfo.ttinclude diff --git a/Microsoft.Toolkit/Diagnostics/Guard.Comparable.Generic.cs b/Microsoft.Toolkit.Diagnostics/Guard.Comparable.Generic.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Guard.Comparable.Generic.cs rename to Microsoft.Toolkit.Diagnostics/Guard.Comparable.Generic.cs diff --git a/Microsoft.Toolkit/Diagnostics/Guard.Comparable.Numeric.cs b/Microsoft.Toolkit.Diagnostics/Guard.Comparable.Numeric.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Guard.Comparable.Numeric.cs rename to Microsoft.Toolkit.Diagnostics/Guard.Comparable.Numeric.cs diff --git a/Microsoft.Toolkit/Diagnostics/Guard.IO.cs b/Microsoft.Toolkit.Diagnostics/Guard.IO.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Guard.IO.cs rename to Microsoft.Toolkit.Diagnostics/Guard.IO.cs diff --git a/Microsoft.Toolkit/Diagnostics/Guard.String.cs b/Microsoft.Toolkit.Diagnostics/Guard.String.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Guard.String.cs rename to Microsoft.Toolkit.Diagnostics/Guard.String.cs diff --git a/Microsoft.Toolkit/Diagnostics/Guard.Tasks.cs b/Microsoft.Toolkit.Diagnostics/Guard.Tasks.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Guard.Tasks.cs rename to Microsoft.Toolkit.Diagnostics/Guard.Tasks.cs diff --git a/Microsoft.Toolkit/Diagnostics/Guard.cs b/Microsoft.Toolkit.Diagnostics/Guard.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Guard.cs rename to Microsoft.Toolkit.Diagnostics/Guard.cs diff --git a/Microsoft.Toolkit/Diagnostics/Internals/Guard.Collection.Generic.ThrowHelper.cs b/Microsoft.Toolkit.Diagnostics/Internals/Guard.Collection.Generic.ThrowHelper.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Internals/Guard.Collection.Generic.ThrowHelper.cs rename to Microsoft.Toolkit.Diagnostics/Internals/Guard.Collection.Generic.ThrowHelper.cs diff --git a/Microsoft.Toolkit/Diagnostics/Internals/Guard.Comparable.Generic.ThrowHelper.cs b/Microsoft.Toolkit.Diagnostics/Internals/Guard.Comparable.Generic.ThrowHelper.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Internals/Guard.Comparable.Generic.ThrowHelper.cs rename to Microsoft.Toolkit.Diagnostics/Internals/Guard.Comparable.Generic.ThrowHelper.cs diff --git a/Microsoft.Toolkit/Diagnostics/Internals/Guard.Comparable.Numeric.ThrowHelper.cs b/Microsoft.Toolkit.Diagnostics/Internals/Guard.Comparable.Numeric.ThrowHelper.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Internals/Guard.Comparable.Numeric.ThrowHelper.cs rename to Microsoft.Toolkit.Diagnostics/Internals/Guard.Comparable.Numeric.ThrowHelper.cs diff --git a/Microsoft.Toolkit/Diagnostics/Internals/Guard.IO.ThrowHelper.cs b/Microsoft.Toolkit.Diagnostics/Internals/Guard.IO.ThrowHelper.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Internals/Guard.IO.ThrowHelper.cs rename to Microsoft.Toolkit.Diagnostics/Internals/Guard.IO.ThrowHelper.cs diff --git a/Microsoft.Toolkit/Diagnostics/Internals/Guard.String.ThrowHelper.cs b/Microsoft.Toolkit.Diagnostics/Internals/Guard.String.ThrowHelper.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Internals/Guard.String.ThrowHelper.cs rename to Microsoft.Toolkit.Diagnostics/Internals/Guard.String.ThrowHelper.cs diff --git a/Microsoft.Toolkit/Diagnostics/Internals/Guard.Tasks.ThrowHelper.cs b/Microsoft.Toolkit.Diagnostics/Internals/Guard.Tasks.ThrowHelper.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Internals/Guard.Tasks.ThrowHelper.cs rename to Microsoft.Toolkit.Diagnostics/Internals/Guard.Tasks.ThrowHelper.cs diff --git a/Microsoft.Toolkit/Diagnostics/Internals/Guard.ThrowHelper.cs b/Microsoft.Toolkit.Diagnostics/Internals/Guard.ThrowHelper.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/Internals/Guard.ThrowHelper.cs rename to Microsoft.Toolkit.Diagnostics/Internals/Guard.ThrowHelper.cs diff --git a/Microsoft.Toolkit.Diagnostics/Microsoft.Toolkit.Diagnostics.csproj b/Microsoft.Toolkit.Diagnostics/Microsoft.Toolkit.Diagnostics.csproj new file mode 100644 index 00000000000..4d541b559e3 --- /dev/null +++ b/Microsoft.Toolkit.Diagnostics/Microsoft.Toolkit.Diagnostics.csproj @@ -0,0 +1,97 @@ + + + + netstandard1.4;netstandard2.0;netstandard2.1;net5.0 + 9.0 + true + enable + Windows Community Toolkit Diagnostics .NET Standard + + This package includes .NET Standard code only helpers such as: + - Guard: Helper methods to verify conditions when running code. + - ThrowHelper: Helper methods to efficiently throw exceptions. + + UWP Toolkit Windows IncrementalLoadingCollection String Array extensions helpers + + + + + + + + + + + + + + + + + + + + + NETSTANDARD2_1_OR_GREATER + + + + + + + + + + NETSTANDARD2_1_OR_GREATER + + + + + + + TextTemplatingFileGenerator + Guard.Comparable.Numeric.g.cs + + + TextTemplatingFileGenerator + Guard.Collection.g.cs + + + TextTemplatingFileGenerator + ThrowHelper.Collection.g.cs + + + TextTemplatingFileGenerator + TypeInfo.g.cs + + + + + + + + + + + True + True + Guard.Comparable.Numeric.tt + + + True + True + Guard.Collection.tt + + + True + True + ThrowHelper.Collection.tt + + + True + True + TypeInfo.ttinclude + + + + diff --git a/Microsoft.Toolkit/Diagnostics/ThrowHelper.Generic.cs b/Microsoft.Toolkit.Diagnostics/ThrowHelper.Generic.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/ThrowHelper.Generic.cs rename to Microsoft.Toolkit.Diagnostics/ThrowHelper.Generic.cs diff --git a/Microsoft.Toolkit/Diagnostics/ThrowHelper.cs b/Microsoft.Toolkit.Diagnostics/ThrowHelper.cs similarity index 100% rename from Microsoft.Toolkit/Diagnostics/ThrowHelper.cs rename to Microsoft.Toolkit.Diagnostics/ThrowHelper.cs diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Default.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Default.cs index 5e15a7de772..1dcbee0c547 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Default.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Default.cs @@ -6,7 +6,6 @@ using System; using System.Numerics; -using Microsoft.Toolkit.Diagnostics; using Windows.UI.Composition; using Windows.UI.Xaml; using Windows.UI.Xaml.Media; @@ -605,7 +604,7 @@ public AnimationBuilder Transform( { if (!Matrix4x4.Decompose(to, out Vector3 toScale, out Quaternion toRotation, out Vector3 toTranslation)) { - ThrowHelper.ThrowArgumentException("The destination matrix could not be decomposed"); + ThrowThrowArgumentExceptionForToDecompose(); } Vector3? fromScale = null; @@ -616,7 +615,7 @@ public AnimationBuilder Transform( { if (!Matrix4x4.Decompose(from.GetValueOrDefault(), out Vector3 scale3, out Quaternion rotation4, out Vector3 translation3)) { - ThrowHelper.ThrowArgumentException("The initial matrix could not be decomposed"); + ThrowThrowArgumentExceptionForFromDecompose(); } fromScale = scale3; @@ -629,6 +628,9 @@ public AnimationBuilder Transform( Translation(toTranslation, fromTranslation, delay, duration, easingType, easingMode); return this; + + static void ThrowThrowArgumentExceptionForToDecompose() => throw new ArgumentException("The destination matrix could not be decomposed"); + static void ThrowThrowArgumentExceptionForFromDecompose() => throw new ArgumentException("The initial matrix could not be decomposed"); } /// diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Factories.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Factories.cs index 455603b2aea..890420badd8 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Factories.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/AnimationBuilder.Factories.cs @@ -6,7 +6,6 @@ using System.Diagnostics.Contracts; using System.Numerics; using System.Runtime.CompilerServices; -using Microsoft.Toolkit.Diagnostics; using Windows.Foundation; using Windows.UI; using Windows.UI.Composition; @@ -161,7 +160,7 @@ public CompositionAnimation GetAnimation(CompositionObject targetHint, out Compo easingFunction); } - return ThrowHelper.ThrowInvalidOperationException("Invalid animation type"); + throw new InvalidOperationException("Invalid animation type"); } /// @@ -216,7 +215,7 @@ public Timeline GetAnimation(DependencyObject targetHint) easingFunction); } - return ThrowHelper.ThrowInvalidOperationException("Invalid animation type"); + throw new InvalidOperationException("Invalid animation type"); } /// @@ -229,9 +228,33 @@ public Timeline GetAnimation(DependencyObject targetHint) private TValue GetToAs() where TValue : unmanaged { - T to = To; - - return Unsafe.As(ref to); + // We employ this (T2)(object)t1 pattern multiple times in this library to alter generics. + // This is an equivalent but safer alternative to using Unsafe.As(ref TFrom). + // For instance, this method will result in the following IL being emitted: + // ============================= + // IL_0000: ldarg.0 + // IL_0001: call instance !0 class AnimationFactory`1::get_To() + // IL_0006: box !T + // IL_000b: unbox.any !!TValue + // IL_0010: ret + // ============================= + // The key point is that the JIT (and AOT compilers such as .NET Native) can recognize this + // pattern and optimize the boxing away in case the types match. This is the case whenever + // the generic arguments are value types, which due to generic types in .NET being reified + // results in a completely different generic instantiation of the same method, making the + // type arguments effectively constant values known at compile time, ie. at JIT time. + // As a result of this, the boxing is completely avoided and the value is returned directly. + // Leveraging this pattern lets us keep the same optimal codegen while avoiding the extra + // NuGet package dependency on UWP, and the more dangerous path using the Unsafe APIs. + // As an example, assuming T is float, the JIT will produce the following codegen on x64: + // ============================= + // L0000: vzeroupper + // L0003: vmovss xmm0, [rcx+8] + // L0008: ret + // ============================= + // We can see how the property value is loaded directly from the underlying field and + // then returned to the caller: no boxing or unwanted overhead is introduced at all. + return (TValue)(object)To; } /// @@ -251,7 +274,7 @@ private TValue GetToAs() T from = From.GetValueOrDefault(); - return Unsafe.As(ref from); + return (TValue)(object)from; } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/Helpers/ListBuilder{T}.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/Helpers/ListBuilder{T}.cs index df9bc575253..b22634fdb0e 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/Helpers/ListBuilder{T}.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/Helpers/ListBuilder{T}.cs @@ -9,7 +9,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Animations.Builders.Helpers { /// - /// A small generic builder type that allows to create instances. + /// A small generic builder type that allows to create instances. /// /// The type of items to create a sequence of. internal struct ListBuilder @@ -56,14 +56,14 @@ public void Append(T item) } /// - /// Gets a instance with the current items. + /// Gets a instance with the current items. /// - /// A instance with the current items. + /// A instance with the current items. [Pure] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan AsSpan() + public ArraySegment GetArraySegment() { - return this.array.AsSpan(0, this.index); + return new(this.array, 0, this.index); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.Composition.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.Composition.cs index e5dc6fb44e8..718ee6781ae 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.Composition.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.Composition.cs @@ -4,7 +4,6 @@ using System; using System.Numerics; -using Microsoft.Toolkit.Diagnostics; using Windows.UI; using Windows.UI.Composition; using Windows.UI.Xaml.Media.Animation; @@ -33,7 +32,7 @@ public static CompositionAnimation GetAnimation( TimeSpan? delay, TimeSpan duration, RepeatOption repeat, - ReadOnlySpan keyFrames) + ArraySegment keyFrames) where TKeyFrame : struct, IKeyFrameInfo { KeyFrameAnimation animation; @@ -42,7 +41,7 @@ public static CompositionAnimation GetAnimation( { BooleanKeyFrameAnimation boolAnimation = target.Compositor.CreateBooleanKeyFrameAnimation(); - foreach (ref readonly var keyFrame in keyFrames) + foreach (var keyFrame in keyFrames) { if (keyFrame.TryInsertExpressionKeyFrame(boolAnimation, duration)) { @@ -58,7 +57,7 @@ public static CompositionAnimation GetAnimation( { ScalarKeyFrameAnimation scalarAnimation = target.Compositor.CreateScalarKeyFrameAnimation(); - foreach (ref readonly var keyFrame in keyFrames) + foreach (var keyFrame in keyFrames) { if (keyFrame.TryInsertExpressionKeyFrame(scalarAnimation, duration)) { @@ -83,7 +82,7 @@ public static CompositionAnimation GetAnimation( { ScalarKeyFrameAnimation scalarAnimation = target.Compositor.CreateScalarKeyFrameAnimation(); - foreach (ref readonly var keyFrame in keyFrames) + foreach (var keyFrame in keyFrames) { if (keyFrame.TryInsertExpressionKeyFrame(scalarAnimation, duration)) { @@ -108,7 +107,7 @@ public static CompositionAnimation GetAnimation( { Vector2KeyFrameAnimation vector2Animation = target.Compositor.CreateVector2KeyFrameAnimation(); - foreach (ref readonly var keyFrame in keyFrames) + foreach (var keyFrame in keyFrames) { if (keyFrame.TryInsertExpressionKeyFrame(vector2Animation, duration)) { @@ -133,7 +132,7 @@ public static CompositionAnimation GetAnimation( { Vector3KeyFrameAnimation vector3Animation = target.Compositor.CreateVector3KeyFrameAnimation(); - foreach (ref readonly var keyFrame in keyFrames) + foreach (var keyFrame in keyFrames) { if (keyFrame.TryInsertExpressionKeyFrame(vector3Animation, duration)) { @@ -158,7 +157,7 @@ public static CompositionAnimation GetAnimation( { Vector4KeyFrameAnimation vector4Animation = target.Compositor.CreateVector4KeyFrameAnimation(); - foreach (ref readonly var keyFrame in keyFrames) + foreach (var keyFrame in keyFrames) { if (keyFrame.TryInsertExpressionKeyFrame(vector4Animation, duration)) { @@ -183,7 +182,7 @@ public static CompositionAnimation GetAnimation( { ColorKeyFrameAnimation colorAnimation = target.Compositor.CreateColorKeyFrameAnimation(); - foreach (ref readonly var keyFrame in keyFrames) + foreach (var keyFrame in keyFrames) { if (keyFrame.TryInsertExpressionKeyFrame(colorAnimation, duration)) { @@ -208,7 +207,7 @@ public static CompositionAnimation GetAnimation( { QuaternionKeyFrameAnimation quaternionAnimation = target.Compositor.CreateQuaternionKeyFrameAnimation(); - foreach (ref readonly var keyFrame in keyFrames) + foreach (var keyFrame in keyFrames) { if (keyFrame.TryInsertExpressionKeyFrame(quaternionAnimation, duration)) { @@ -231,7 +230,7 @@ public static CompositionAnimation GetAnimation( } else { - return ThrowHelper.ThrowInvalidOperationException("Invalid animation type"); + throw new InvalidOperationException("Invalid animation type"); } animation.Duration = duration; @@ -284,7 +283,7 @@ public CompositionAnimation GetAnimation(CompositionObject targetHint, out Compo this.delay, this.duration, this.repeat, - this.keyFrames.AsSpan()); + this.keyFrames.GetArraySegment()); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.Xaml.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.Xaml.cs index 23665b9544b..a5727d42d0b 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.Xaml.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.Xaml.cs @@ -45,7 +45,7 @@ public Timeline GetAnimation(DependencyObject targetHint) this.delay, this.duration, this.repeat, - this.keyFrames.AsSpan()); + this.keyFrames.GetArraySegment()); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.cs index ef707c415d6..4542c36551b 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/NormalizedKeyFrameAnimationBuilder{T}.cs @@ -150,7 +150,7 @@ public KeyFrameInfo( [MethodImpl(MethodImplOptions.AggressiveInlining)] public TValue GetValueAs() { - return Unsafe.As(ref Unsafe.AsRef(in this.value)); + return (TValue)(object)this.value; } /// diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.Composition.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.Composition.cs index 066e7ad6c1a..772aa7f90a7 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.Composition.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.Composition.cs @@ -47,8 +47,8 @@ public CompositionAnimation GetAnimation(CompositionObject targetHint, out Compo // We can retrieve the total duration from the last timed keyframe, and then set // this as the target duration and use it to normalize the keyframe progresses. - ReadOnlySpan keyFrames = this.keyFrames.AsSpan(); - TimeSpan duration = keyFrames[keyFrames.Length - 1].GetTimedProgress(default); + ArraySegment keyFrames = this.keyFrames.GetArraySegment(); + TimeSpan duration = keyFrames[keyFrames.Count - 1].GetTimedProgress(default); return NormalizedKeyFrameAnimationBuilder.GetAnimation( targetHint, diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.Xaml.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.Xaml.cs index ee6042a7a07..1c73463697b 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.Xaml.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.Xaml.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using Microsoft.Toolkit.Diagnostics; using Windows.Foundation; using Windows.UI; using Windows.UI.Xaml; @@ -32,7 +31,7 @@ public static Timeline GetAnimation( TimeSpan? delay, TimeSpan duration, RepeatOption repeat, - ReadOnlySpan keyFrames) + ArraySegment keyFrames) where TKeyFrame : struct, IKeyFrameInfo { Timeline animation; @@ -118,7 +117,9 @@ public static Timeline GetAnimation( } else { - return ThrowHelper.ThrowInvalidOperationException("Invalid animation type"); + static Timeline ThrowInvalidOperationException() => throw new InvalidOperationException("Invalid animation type"); + + return ThrowInvalidOperationException(); } animation.BeginTime = delay; @@ -163,7 +164,7 @@ public Timeline GetAnimation(DependencyObject targetHint) this.delay, default, this.repeat, - this.keyFrames.AsSpan()); + this.keyFrames.GetArraySegment()); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.cs index 6c0368d6f55..8a55f7d296f 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Builders/TimedKeyFrameAnimationBuilder{T}.cs @@ -143,7 +143,7 @@ public KeyFrameInfo( [MethodImpl(MethodImplOptions.AggressiveInlining)] public TValue GetValueAs() { - return Unsafe.As(ref Unsafe.AsRef(in this.value)); + return (TValue)(object)this.value; } /// diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/AnimationExtensions.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/AnimationExtensions.cs index e40c9033170..ae4081f56f1 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/AnimationExtensions.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/AnimationExtensions.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Numerics; -using Microsoft.Toolkit.Diagnostics; using Windows.UI.Composition; using Windows.UI.Xaml; using Windows.UI.Xaml.Media; @@ -111,7 +110,7 @@ public static class Composition Axis.X => "AnchorPoint.X", Axis.Y => "AnchorPoint.Y", Axis.Z => "AnchorPoint.Z", - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; /// @@ -132,7 +131,7 @@ public static class Composition Axis.X => "Translation.X", Axis.Y => "Translation.Y", Axis.Z => "Translation.Z", - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; /// @@ -153,7 +152,7 @@ public static class Composition Axis.X => "Offset.X", Axis.Y => "Offset.Y", Axis.Z => "Offset.Z", - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; /// @@ -174,7 +173,7 @@ public static class Composition Axis.X => "Scale.X", Axis.Y => "Scale.Y", Axis.Z => "Scale.Z", - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; /// @@ -195,7 +194,7 @@ public static class Composition Axis.X => "CenterPoint.X", Axis.Y => "CenterPoint.Y", Axis.Z => "CenterPoint.Z", - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; /// @@ -217,7 +216,7 @@ public static class Composition Side.Bottom => nameof(InsetClip.BottomInset), Side.Right => nameof(InsetClip.RightInset), Side.Left => nameof(InsetClip.LeftInset), - _ => ThrowHelper.ThrowArgumentException("Invalid clip side") + _ => ThrowArgumentException("Invalid clip side") }; /// @@ -238,7 +237,7 @@ public static class Composition Axis.X => "Size.X", Axis.Y => "Size.Y", Axis.Z => "Size.Z", - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; } @@ -257,7 +256,7 @@ public static class Xaml { Axis.X => nameof(CompositeTransform.TranslateX), Axis.Y => nameof(CompositeTransform.TranslateY), - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; /// @@ -270,7 +269,7 @@ public static class Xaml { Axis.X => nameof(CompositeTransform.ScaleX), Axis.Y => nameof(CompositeTransform.ScaleY), - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; /// @@ -283,7 +282,7 @@ public static class Xaml { Axis.X => nameof(CompositeTransform.CenterX), Axis.Y => nameof(CompositeTransform.CenterY), - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; /// @@ -296,9 +295,17 @@ public static class Xaml { Axis.X => nameof(FrameworkElement.Width), Axis.Y => nameof(FrameworkElement.Height), - _ => ThrowHelper.ThrowArgumentException("Invalid axis") + _ => ThrowArgumentException("Invalid axis") }; } + + /// + /// Throws a new with a given message. + /// + private static T ThrowArgumentException(string message) + { + throw new ArgumentException(message); + } } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/EasingTypeExtensions.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/EasingTypeExtensions.cs index 039f807f4f5..325a0cb6814 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/EasingTypeExtensions.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/EasingTypeExtensions.cs @@ -4,8 +4,8 @@ #nullable enable +using System; using System.Diagnostics.Contracts; -using Microsoft.Toolkit.Diagnostics; using Windows.UI.Xaml.Media.Animation; using static Microsoft.Toolkit.Uwp.UI.Animations.AnimationExtensions; @@ -46,8 +46,10 @@ public static class EasingTypeExtensions EasingType.Quintic => new QuinticEase { EasingMode = easingMode }, EasingType.Sine => new SineEase { EasingMode = easingMode }, - _ => ThrowHelper.ThrowArgumentException("Invalid easing type") + _ => ThrowArgumentException() }; + + static EasingFunctionBase ThrowArgumentException() => throw new ArgumentException("Invalid easing type"); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/ScrollViewerExtensions.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/ScrollViewerExtensions.cs index a11b6b27b11..09bf2781bf4 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/ScrollViewerExtensions.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Extensions/ScrollViewerExtensions.cs @@ -2,8 +2,8 @@ // 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.Numerics; -using Microsoft.Toolkit.Diagnostics; using Windows.UI.Composition; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -66,11 +66,13 @@ public static ExpressionAnimation StartExpressionAnimation( visual.StartAnimation($"{nameof(Visual.Offset)}.{targetAxis}", animation); break; default: - ThrowHelper.ThrowArgumentException("Invalid target property"); + ThrowArgumentException(); break; } return animation; + + static ExpressionAnimation ThrowArgumentException() => throw new ArgumentException("Invalid target property"); } } } \ No newline at end of file diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Options/RepeatOption.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Options/RepeatOption.cs index 62515f7a833..58ee14c03fd 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Options/RepeatOption.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Options/RepeatOption.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics.Contracts; -using Microsoft.Toolkit.Diagnostics; using Windows.Foundation.Metadata; using Windows.UI.Composition; using Windows.UI.Xaml.Media.Animation; @@ -52,7 +51,10 @@ private RepeatOption(int value) [Pure] public static RepeatOption Count(int count) { - Guard.IsGreaterThanOrEqualTo(count, 0, nameof(count)); + if (count < 0) + { + ThrowArgumentOutOfRangeForCount(); + } return new(count); } @@ -76,7 +78,7 @@ public static RepeatOption Parse(string text) return Forever; } - return ThrowHelper.ThrowArgumentException("Invalid input text"); + return ThrowArgumentExceptionForText(); } /// @@ -109,5 +111,21 @@ public RepeatBehavior ToRepeatBehavior() return (AnimationIterationBehavior.Count, this.value); } + + /// + /// Throws a new when the constructor is invoked with an incorrect parameter. + /// + private static void ThrowArgumentOutOfRangeForCount() + { + throw new ArgumentOutOfRangeException("The parameter \"count\" must be greater than or equal to 0."); + } + + /// + /// Throws a new when the constructor is invoked with an incorrect parameter. + /// + private static RepeatOption ThrowArgumentExceptionForText() + { + throw new ArgumentException("The input text is not valid to parse a new RepeatOption instance. It must be either a natural number or \"Forever\"."); + } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Activities/StartAnimationActivity.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Activities/StartAnimationActivity.cs index 3abc6a08e84..c74a4c5c533 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Activities/StartAnimationActivity.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Activities/StartAnimationActivity.cs @@ -2,9 +2,9 @@ // 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.Threading; using System.Threading.Tasks; -using Microsoft.Toolkit.Diagnostics; using Windows.UI.Xaml; namespace Microsoft.Toolkit.Uwp.UI.Animations @@ -53,7 +53,10 @@ public UIElement TargetObject /// public override async Task InvokeAsync(UIElement element, CancellationToken token) { - Guard.IsNotNull(Animation, nameof(Animation)); + if (Animation is null) + { + ThrowArgumentNullException(); + } await base.InvokeAsync(element, token); @@ -72,6 +75,8 @@ public override async Task InvokeAsync(UIElement element, CancellationToken toke { await Animation.StartAsync(token); } + + static void ThrowArgumentNullException() => throw new ArgumentNullException(nameof(Animation)); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Activities/StopAnimationActivity.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Activities/StopAnimationActivity.cs index 58a174ea7f2..6fb686ccb82 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Activities/StopAnimationActivity.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/Activities/StopAnimationActivity.cs @@ -2,9 +2,9 @@ // 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.Threading; using System.Threading.Tasks; -using Microsoft.Toolkit.Diagnostics; using Windows.UI.Xaml; namespace Microsoft.Toolkit.Uwp.UI.Animations @@ -53,7 +53,10 @@ public UIElement TargetObject /// public override async Task InvokeAsync(UIElement element, CancellationToken token) { - Guard.IsNotNull(Animation, nameof(Animation)); + if (Animation is null) + { + ThrowArgumentNullException(); + } await base.InvokeAsync(element, token); @@ -69,6 +72,8 @@ public override async Task InvokeAsync(UIElement element, CancellationToken toke { Animation.Stop(); } + + static void ThrowArgumentNullException() => throw new ArgumentNullException(nameof(Animation)); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/AnimationSet.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/AnimationSet.cs index 22441c8409f..c2cefeb6a6e 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/AnimationSet.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/AnimationSet.cs @@ -9,7 +9,6 @@ using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; -using Microsoft.Toolkit.Diagnostics; using Windows.UI.Xaml; namespace Microsoft.Toolkit.Uwp.UI.Animations @@ -218,10 +217,12 @@ private UIElement GetParent() if (ParentReference?.TryGetTarget(out parent) != true) { - ThrowHelper.ThrowInvalidOperationException("The current animation collection isn't bound to a parent UIElement instance."); + ThrowInvalidOperationException(); } return parent!; + + static void ThrowInvalidOperationException() => throw new InvalidOperationException("The current AnimationSet object isn't bound to a parent UIElement instance."); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/ImplicitAnimationSet.cs b/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/ImplicitAnimationSet.cs index 2cbf0da37c2..eda7836e7f4 100644 --- a/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/ImplicitAnimationSet.cs +++ b/Microsoft.Toolkit.Uwp.UI.Animations/Xaml/ImplicitAnimationSet.cs @@ -6,7 +6,6 @@ using System; using System.Diagnostics.Contracts; -using Microsoft.Toolkit.Diagnostics; using Windows.UI.Composition; using Windows.UI.Xaml; using Windows.UI.Xaml.Hosting; @@ -85,10 +84,12 @@ private UIElement GetParent() if (ParentReference?.TryGetTarget(out parent) != true) { - ThrowHelper.ThrowInvalidOperationException("The current animation collection isn't bound to a parent UIElement instance."); + ThrowInvalidOperationException(); } return parent!; + + static void ThrowInvalidOperationException() => throw new InvalidOperationException("The current ImplicitAnimationSet object isn't bound to a parent UIElement instance."); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Behaviors/Animations/StartAnimationAction.cs b/Microsoft.Toolkit.Uwp.UI.Behaviors/Animations/StartAnimationAction.cs index aa75926d7fc..72f65dec6cf 100644 --- a/Microsoft.Toolkit.Uwp.UI.Behaviors/Animations/StartAnimationAction.cs +++ b/Microsoft.Toolkit.Uwp.UI.Behaviors/Animations/StartAnimationAction.cs @@ -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 Microsoft.Toolkit.Diagnostics; +using System; using Microsoft.Toolkit.Uwp.UI.Animations; using Microsoft.Xaml.Interactivity; using Windows.UI.Xaml; @@ -53,7 +53,10 @@ public UIElement TargetObject /// public object Execute(object sender, object parameter) { - Guard.IsNotNull(Animation, nameof(Animation)); + if (Animation is null) + { + ThrowArgumentNullException(); + } if (TargetObject is not null) { @@ -65,6 +68,8 @@ public object Execute(object sender, object parameter) } return null!; + + static void ThrowArgumentNullException() => throw new ArgumentNullException(nameof(Animation)); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Behaviors/Animations/StopAnimationAction.cs b/Microsoft.Toolkit.Uwp.UI.Behaviors/Animations/StopAnimationAction.cs index 52f889b6bdd..c8f2a197950 100644 --- a/Microsoft.Toolkit.Uwp.UI.Behaviors/Animations/StopAnimationAction.cs +++ b/Microsoft.Toolkit.Uwp.UI.Behaviors/Animations/StopAnimationAction.cs @@ -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 Microsoft.Toolkit.Diagnostics; +using System; using Microsoft.Toolkit.Uwp.UI.Animations; using Microsoft.Xaml.Interactivity; using Windows.UI.Xaml; @@ -53,7 +53,10 @@ public UIElement TargetObject /// public object Execute(object sender, object parameter) { - Guard.IsNotNull(Animation, nameof(Animation)); + if (Animation is null) + { + ThrowArgumentNullException(); + } if (TargetObject is not null) { @@ -65,6 +68,8 @@ public object Execute(object sender, object parameter) } return null!; + + static void ThrowArgumentNullException() => throw new ArgumentNullException(nameof(Animation)); } } } diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/ColorPicker/ColorPicker.cs b/Microsoft.Toolkit.Uwp.UI.Controls/ColorPicker/ColorPicker.cs index cb7398d9791..8dbe534bf94 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/ColorPicker/ColorPicker.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/ColorPicker/ColorPicker.cs @@ -3,14 +3,11 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Globalization; -using Microsoft.Toolkit.Diagnostics; using Microsoft.Toolkit.Uwp.Helpers; using Microsoft.Toolkit.Uwp.UI.Controls.ColorPickerConverters; -using Windows.Foundation; using Windows.UI; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; @@ -233,10 +230,12 @@ private T GetTemplateChild(string childName, bool isRequired = false) T child = this.GetTemplateChild(childName) as T; if ((child == null) && isRequired) { - ThrowHelper.ThrowArgumentNullException(childName); + ThrowArgumentNullException(); } return child; + + static void ThrowArgumentNullException() => throw new ArgumentNullException(nameof(childName)); } /// diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/TokenizingTextBox/InterspersedObservableCollection.cs b/Microsoft.Toolkit.Uwp.UI.Controls/TokenizingTextBox/InterspersedObservableCollection.cs index 74fc28fd5d1..c0c84fef849 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/TokenizingTextBox/InterspersedObservableCollection.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/TokenizingTextBox/InterspersedObservableCollection.cs @@ -5,11 +5,8 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.Immutable; using System.Collections.Specialized; -using System.ComponentModel; using System.Linq; -using Microsoft.Toolkit.Diagnostics; using Microsoft.Toolkit.Uwp.Helpers; namespace Microsoft.Toolkit.Uwp.UI.Controls @@ -54,9 +51,12 @@ public object this[int index] public InterspersedObservableCollection(object itemsSource) { - Guard.IsAssignableToType(itemsSource, nameof(itemsSource)); + if (!(itemsSource is IList list)) + { + ThrowArgumentException(); + } - ItemsSource = itemsSource as IList; + ItemsSource = list; if (ItemsSource is INotifyCollectionChanged notifier) { @@ -67,6 +67,8 @@ public InterspersedObservableCollection(object itemsSource) }; notifier.CollectionChanged += weakPropertyChangedListener.OnEvent; } + + static void ThrowArgumentException() => throw new ArgumentNullException("The input items source must be assignable to the System.Collections.IList type."); } private void ItemsSource_CollectionChanged(object source, NotifyCollectionChangedEventArgs eventArgs) @@ -192,12 +194,20 @@ private void ReadjustKeys() /// Inner ItemsSource Index. private int ToInnerIndex(int outerIndex) { -#if DEBUG - Guard.IsInRange(outerIndex, 0, Count, nameof(outerIndex)); - Guard.IsFalse(_interspersedObjects.ContainsKey(outerIndex), nameof(outerIndex)); // We can't map a inserted key to the original collection! -#endif + if ((uint)outerIndex >= Count) + { + ThrowArgumentOutOfRangeException(); + } + + if (_interspersedObjects.ContainsKey(outerIndex)) + { + ThrowArgumentException(); + } return outerIndex - _interspersedObjects.Keys.Count(key => key.Value <= outerIndex); + + static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException(nameof(outerIndex)); + static void ThrowArgumentException() => throw new ArgumentException("The outer index can't be inserted as a key to the original collection."); } /// @@ -207,9 +217,10 @@ private int ToInnerIndex(int outerIndex) /// Index into the entire collection. private int ToOuterIndex(int innerIndex) { -#if DEBUG - Guard.IsInRange(innerIndex, 0, ItemsSource.Count, nameof(innerIndex)); -#endif + if ((uint)innerIndex >= ItemsSource.Count) + { + ThrowArgumentOutOfRangeException(); + } var keys = _interspersedObjects.OrderBy(v => v.Key); @@ -226,6 +237,8 @@ private int ToOuterIndex(int innerIndex) } return innerIndex; + + static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException(nameof(innerIndex)); } /// @@ -235,9 +248,10 @@ private int ToOuterIndex(int innerIndex) /// Projected index in the entire collection. private int ToOuterIndexAfterRemoval(int innerIndexToProject) { -#if DEBUG - Guard.IsInRange(innerIndexToProject, 0, ItemsSource.Count + 1, nameof(innerIndexToProject)); -#endif + if ((uint)innerIndexToProject >= ItemsSource.Count + 1) + { + ThrowArgumentOutOfRangeException(); + } //// TODO: Deal with bounds (0 / Count)? Or is it the same? @@ -256,6 +270,8 @@ private int ToOuterIndexAfterRemoval(int innerIndexToProject) } return innerIndexToProject; + + static void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException(nameof(innerIndexToProject)); } /// diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/UniformGrid/TakenSpotsReferenceHolder.cs b/Microsoft.Toolkit.Uwp.UI.Controls/UniformGrid/TakenSpotsReferenceHolder.cs index 9474082e25e..0092a1275cb 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/UniformGrid/TakenSpotsReferenceHolder.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/UniformGrid/TakenSpotsReferenceHolder.cs @@ -4,7 +4,6 @@ using System.Collections; using System.Drawing; -using Microsoft.Toolkit.Diagnostics; namespace Microsoft.Toolkit.Uwp.UI.Controls { @@ -28,9 +27,6 @@ internal sealed class TakenSpotsReferenceHolder /// The number of columns to track. public TakenSpotsReferenceHolder(int rows, int columns) { - Guard.IsGreaterThanOrEqualTo(rows, 0, nameof(rows)); - Guard.IsGreaterThanOrEqualTo(columns, 0, nameof(columns)); - Height = rows; Width = columns; diff --git a/Microsoft.Toolkit.Uwp.UI.Controls/WrapPanel/WrapPanel.Data.cs b/Microsoft.Toolkit.Uwp.UI.Controls/WrapPanel/WrapPanel.Data.cs index c3112d9bd96..cf8ac47ed52 100644 --- a/Microsoft.Toolkit.Uwp.UI.Controls/WrapPanel/WrapPanel.Data.cs +++ b/Microsoft.Toolkit.Uwp.UI.Controls/WrapPanel/WrapPanel.Data.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using Microsoft.Toolkit.Diagnostics; using Windows.Foundation; using Windows.UI.Xaml.Controls; @@ -63,8 +62,10 @@ private struct UvRect { Orientation.Vertical => new Rect(Position.V, Position.U, Size.V, Size.U), Orientation.Horizontal => new Rect(Position.U, Position.V, Size.U, Size.V), - _ => ThrowHelper.ThrowNotSupportedException("unsupported orientation"), + _ => ThrowArgumentException() }; + + private static Rect ThrowArgumentException() => throw new ArgumentException("The input orientation is not valid."); } private struct Row diff --git a/Microsoft.Toolkit.Uwp.UI.Media/Animations/Abstract/EffectAnimation{TEffect,TValue,TKeyFrame}.cs b/Microsoft.Toolkit.Uwp.UI.Media/Animations/Abstract/EffectAnimation{TEffect,TValue,TKeyFrame}.cs index b2f2f697824..faaa78dd171 100644 --- a/Microsoft.Toolkit.Uwp.UI.Media/Animations/Abstract/EffectAnimation{TEffect,TValue,TKeyFrame}.cs +++ b/Microsoft.Toolkit.Uwp.UI.Media/Animations/Abstract/EffectAnimation{TEffect,TValue,TKeyFrame}.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using Microsoft.Toolkit.Diagnostics; using Microsoft.Toolkit.Uwp.UI.Media; using Windows.UI.Composition; using Windows.UI.Xaml; @@ -50,14 +49,21 @@ public override AnimationBuilder AppendToBuilder(AnimationBuilder builder, TimeS { if (Target is not TEffect target) { - return ThrowHelper.ThrowArgumentNullException("The target effect is null, make sure to set the Target property"); + static AnimationBuilder ThrowArgumentNullException() => throw new ArgumentNullException("The target effect is null, make sure to set the Target property"); + + return ThrowArgumentNullException(); } if (ExplicitTarget is not string explicitTarget) { - return ThrowHelper.ThrowArgumentNullException( - "The target effect cannot be animated at this time. If you're targeting one of the " + - "built-in effects, make sure that the PipelineEffect.IsAnimatable property is set to true."); + static AnimationBuilder ThrowArgumentNullException() + { + throw new ArgumentNullException( + "The target effect cannot be animated at this time. If you're targeting one of the " + + "built-in effects, make sure that the PipelineEffect.IsAnimatable property is set to true."); + } + + return ThrowArgumentNullException(); } NormalizedKeyFrameAnimationBuilder.Composition keyFrameBuilder = new( @@ -70,7 +76,7 @@ public override AnimationBuilder AppendToBuilder(AnimationBuilder builder, TimeS CompositionAnimation animation = keyFrameBuilder.GetAnimation(target.Brush!, out _); - return builder.ExternalAnimation(target.Brush, animation); + return builder.ExternalAnimation(target.Brush!, animation); } } } diff --git a/Microsoft.Toolkit.Uwp.UI/Extensions/Visual/VisualExtensions.cs b/Microsoft.Toolkit.Uwp.UI/Extensions/Visual/VisualExtensions.cs index 85b3770dab1..1b2b323b15d 100644 --- a/Microsoft.Toolkit.Uwp.UI/Extensions/Visual/VisualExtensions.cs +++ b/Microsoft.Toolkit.Uwp.UI/Extensions/Visual/VisualExtensions.cs @@ -6,7 +6,6 @@ using System.Globalization; using System.Linq; using System.Numerics; -using System.Runtime.CompilerServices; using Windows.UI.Composition; using Windows.UI.Xaml; using Windows.UI.Xaml.Hosting; @@ -165,11 +164,11 @@ public static Vector4 ToVector4(this string str) /// /// A string in the format of "float, float, float, float" /// - public static Quaternion ToQuaternion(this string str) + public static unsafe Quaternion ToQuaternion(this string str) { Vector4 vector = str.ToVector4(); - return Unsafe.As(ref vector); + return *(Quaternion*)&vector; } /// diff --git a/Microsoft.Toolkit.Uwp.UI/Helpers/CompositionTargetHelper.cs b/Microsoft.Toolkit.Uwp.UI/Helpers/CompositionTargetHelper.cs index 08a6741cf50..24a7bc18801 100644 --- a/Microsoft.Toolkit.Uwp.UI/Helpers/CompositionTargetHelper.cs +++ b/Microsoft.Toolkit.Uwp.UI/Helpers/CompositionTargetHelper.cs @@ -4,7 +4,6 @@ using System; using System.Threading.Tasks; -using Microsoft.Toolkit.Diagnostics; using Windows.UI.Xaml.Media; namespace Microsoft.Toolkit.Uwp.UI.Helpers @@ -22,7 +21,10 @@ public static class CompositionTargetHelper /// Awaitable Task public static Task ExecuteAfterCompositionRenderingAsync(Action action) { - Guard.IsNotNull(action, nameof(action)); + if (action is null) + { + ThrowArgumentNullException(); + } var taskCompletionSource = new TaskCompletionSource(); @@ -45,6 +47,8 @@ void Callback(object sender, object args) } return taskCompletionSource.Task; + + static void ThrowArgumentNullException() => throw new ArgumentNullException("The parameter \"action\" must not be null."); } } } diff --git a/Microsoft.Toolkit.Uwp.UI/Microsoft.Toolkit.Uwp.UI.csproj b/Microsoft.Toolkit.Uwp.UI/Microsoft.Toolkit.Uwp.UI.csproj index edb24421aca..e7358bf1939 100644 --- a/Microsoft.Toolkit.Uwp.UI/Microsoft.Toolkit.Uwp.UI.csproj +++ b/Microsoft.Toolkit.Uwp.UI/Microsoft.Toolkit.Uwp.UI.csproj @@ -40,8 +40,8 @@ - ThemeListener: Class which listens for changes to Application Theme or High Contrast Modes and Signals an Event when they occur. UWP Toolkit Windows UI Converters XAML extensions helpers - true + true diff --git a/Microsoft.Toolkit.Uwp/Helpers/ColorHelper.cs b/Microsoft.Toolkit.Uwp/Helpers/ColorHelper.cs index f3f82615034..ff6cb38c314 100644 --- a/Microsoft.Toolkit.Uwp/Helpers/ColorHelper.cs +++ b/Microsoft.Toolkit.Uwp/Helpers/ColorHelper.cs @@ -5,7 +5,6 @@ using System; using System.Globalization; using System.Reflection; -using Microsoft.Toolkit.Diagnostics; using Windows.UI; using Color = Windows.UI.Color; @@ -24,7 +23,10 @@ public static class ColorHelper /// The created . public static Color ToColor(this string colorString) { - Guard.IsNotNullOrEmpty(colorString, nameof(colorString)); + if (string.IsNullOrEmpty(colorString)) + { + ThrowArgumentException(); + } if (colorString[0] == '#') { @@ -79,7 +81,7 @@ public static Color ToColor(this string colorString) return Color.FromArgb(255, r, g, b); } - default: return ThrowHelper.ThrowFormatException("The string passed in the colorString argument is not a recognized Color format."); + default: return ThrowFormatException(); } } @@ -106,7 +108,7 @@ public static Color ToColor(this string colorString) return Color.FromArgb(255, (byte)(scR * 255), (byte)(scG * 255), (byte)(scB * 255)); } - return ThrowHelper.ThrowFormatException("The string passed in the colorString argument is not a recognized Color format (sc#[scA,]scR,scG,scB)."); + return ThrowFormatException(); } var prop = typeof(Colors).GetTypeInfo().GetDeclaredProperty(colorString); @@ -116,7 +118,10 @@ public static Color ToColor(this string colorString) return (Color)prop.GetValue(null); } - return ThrowHelper.ThrowFormatException("The string passed in the colorString argument is not a recognized Color."); + return ThrowFormatException(); + + static void ThrowArgumentException() => throw new ArgumentException("The parameter \"colorString\" must not be null or empty."); + static Color ThrowFormatException() => throw new FormatException("The parameter \"colorString\" is not a recognized Color format."); } /// diff --git a/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/SystemSerializer.cs b/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/SystemSerializer.cs index 61f247d3eed..07da5edd20f 100644 --- a/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/SystemSerializer.cs +++ b/Microsoft.Toolkit.Uwp/Helpers/ObjectStorage/SystemSerializer.cs @@ -4,7 +4,6 @@ using System; using System.Reflection; -using Microsoft.Toolkit.Diagnostics; using Windows.Storage; namespace Microsoft.Toolkit.Uwp.Helpers @@ -31,7 +30,9 @@ public T Deserialize(object value) return (T)Convert.ChangeType(value, type); } - return ThrowHelper.ThrowNotSupportedException("This serializer can only handle primitive types and strings. Please implement your own IObjectSerializer for more complex scenarios."); + return ThrowNotSupportedException(); + + static T ThrowNotSupportedException() => throw new NotSupportedException("This serializer can only handle primitive types and strings. Please implement your own IObjectSerializer for more complex scenarios."); } /// diff --git a/Microsoft.Toolkit/Microsoft.Toolkit.csproj b/Microsoft.Toolkit/Microsoft.Toolkit.csproj index b071ab13cdb..eaaa8c91009 100644 --- a/Microsoft.Toolkit/Microsoft.Toolkit.csproj +++ b/Microsoft.Toolkit/Microsoft.Toolkit.csproj @@ -13,85 +13,15 @@ UWP Toolkit Windows IncrementalLoadingCollection String Array extensions helpers - - - - - - - - - - - - - - - - - - - NETSTANDARD2_1_OR_GREATER - - - - - - - - - - NETSTANDARD2_1_OR_GREATER - - - - - - - TextTemplatingFileGenerator - Guard.Comparable.Numeric.g.cs - - - TextTemplatingFileGenerator - Guard.Collection.g.cs - - - TextTemplatingFileGenerator - ThrowHelper.Collection.g.cs - - - TextTemplatingFileGenerator - TypeInfo.g.cs - + + + - - - - - - - - True - True - Guard.Comparable.Numeric.tt - - - True - True - Guard.Collection.tt - - - True - True - ThrowHelper.Collection.tt - - - True - True - TypeInfo.ttinclude - - + + + NETSTANDARD2_1_OR_GREATER + diff --git a/SmokeTests/Microsoft.Toolkit.Diagnostics/MainPage.xaml b/SmokeTests/Microsoft.Toolkit.Diagnostics/MainPage.xaml new file mode 100644 index 00000000000..f1f78423b2d --- /dev/null +++ b/SmokeTests/Microsoft.Toolkit.Diagnostics/MainPage.xaml @@ -0,0 +1,18 @@ + + + + + +