From 645c5e4f658f60521b2d2a3fd87c9eda58080b23 Mon Sep 17 00:00:00 2001 From: Sebastian Krysmanski Date: Mon, 18 Mar 2024 16:12:36 +0100 Subject: [PATCH] Add support for "Half", "Int128", and "UInt128" to numeric extension methods --- .../Extensions/TypeExtensions.cs | 156 +++++++++++------- .../Tests/Extensions/TypeExtensionsTests.cs | 126 +++++++------- 2 files changed, 169 insertions(+), 113 deletions(-) diff --git a/src/AppMotor.Core/Extensions/TypeExtensions.cs b/src/AppMotor.Core/Extensions/TypeExtensions.cs index eec2a310..54a7445e 100644 --- a/src/AppMotor.Core/Extensions/TypeExtensions.cs +++ b/src/AppMotor.Core/Extensions/TypeExtensions.cs @@ -21,11 +21,6 @@ public static class TypeExtensions /// and sbyte as well as . However, /// is excluded. /// - /// - /// This method checks the type's full name but ignores the type's assembly. It's therefor - /// not 100% foolproof. However, the chance that someone recreates one of the system types - /// which then should not be a numeric value is rather slim (or even impossible?). - /// /// /// [MustUseReturnValue] @@ -33,38 +28,55 @@ public static bool IsNumericType(this Type type) { Validate.ArgumentWithName(nameof(type)).IsNotNull(type); - switch (type.FullName) + if (type.IsPrimitive) { - case "System.Byte": - case "System.SByte": - case "System.Int16": - case "System.UInt16": - case "System.Int32": - case "System.UInt32": - case "System.Int64": - case "System.UInt64": - case "System.Numerics.BigInteger": - return true; - - case "System.Single": - case "System.Double": - case "System.Decimal": - return true; + switch (type.FullName) + { + case "System.Byte": + case "System.SByte": + case "System.Int16": + case "System.UInt16": + case "System.Int32": + case "System.UInt32": + case "System.Int64": + case "System.UInt64": + return true; - default: - return false; + case "System.Single": + case "System.Double": + return true; + + default: + return false; + } + } + else if (type.IsValueType) + { + switch (type.FullName) + { + case "System.Int128": + case "System.UInt128": + case "System.Numerics.BigInteger": + return true; + + case "System.Half": + case "System.Decimal": + return true; + + default: + return false; + } + } + else + { + return false; } } /// - /// Returns whether this type is an integer type. This list includes byte - /// and sbyte as well as . + /// Returns whether this type is an integer type. This list includes byte, sbyte, , + /// Int128, and UInt128. /// - /// - /// This method checks the type's full name but ignores the type's assembly. It's therefor - /// not 100% foolproof. However, the chance that someone recreates one of the system types - /// which then should not be a numeric value is rather slim (or even impossible?). - /// /// /// [MustUseReturnValue] @@ -72,33 +84,47 @@ public static bool IsNumericIntegerType(this Type type) { Validate.ArgumentWithName(nameof(type)).IsNotNull(type); - switch (type.FullName) + if (type.IsPrimitive) { - case "System.Byte": - case "System.SByte": - case "System.Int16": - case "System.UInt16": - case "System.Int32": - case "System.UInt32": - case "System.Int64": - case "System.UInt64": - case "System.Numerics.BigInteger": - return true; + switch (type.FullName) + { + case "System.Byte": + case "System.SByte": + case "System.Int16": + case "System.UInt16": + case "System.Int32": + case "System.UInt32": + case "System.Int64": + case "System.UInt64": + return true; - default: - return false; + default: + return false; + } + } + else if (type.IsValueType) + { + switch (type.FullName) + { + case "System.Int128": + case "System.UInt128": + case "System.Numerics.BigInteger": + return true; + + default: + return false; + } + } + else + { + return false; } } /// /// Returns whether this type is a floating point type. This list includes float, - /// double and decimal. + /// double, decimal, and Half. /// - /// - /// This method checks the type's full name but ignores the type's assembly. It's therefor - /// not 100% foolproof. However, the chance that someone recreates one of the system types - /// which then should not be a numeric value is rather slim (or even impossible?). - /// /// /// [MustUseReturnValue] @@ -106,15 +132,33 @@ public static bool IsNumericFloatType(this Type type) { Validate.ArgumentWithName(nameof(type)).IsNotNull(type); - switch (type.FullName) + if (type.IsPrimitive) { - case "System.Single": - case "System.Double": - case "System.Decimal": - return true; + switch (type.FullName) + { + case "System.Single": + case "System.Double": + return true; - default: - return false; + default: + return false; + } + } + else if (type.IsValueType) + { + switch (type.FullName) + { + case "System.Half": + case "System.Decimal": + return true; + + default: + return false; + } + } + else + { + return false; } } diff --git a/tests/AppMotor.Core.Tests/Tests/Extensions/TypeExtensionsTests.cs b/tests/AppMotor.Core.Tests/Tests/Extensions/TypeExtensionsTests.cs index 8895e65c..960a1772 100644 --- a/tests/AppMotor.Core.Tests/Tests/Extensions/TypeExtensionsTests.cs +++ b/tests/AppMotor.Core.Tests/Tests/Extensions/TypeExtensionsTests.cs @@ -14,70 +14,82 @@ namespace AppMotor.Core.Tests.Extensions; public sealed class TypeExtensionsTests { - [Fact] - public void Test_IsNumericType() + [Theory] + [InlineData(typeof(string), false)] + [InlineData(typeof(char), false)] + [InlineData(typeof(bool), false)] + [InlineData(typeof(IntPtr), false)] + [InlineData(typeof(UIntPtr), false)] + [InlineData(typeof(byte), true)] + [InlineData(typeof(sbyte), true)] + [InlineData(typeof(short), true)] + [InlineData(typeof(ushort), true)] + [InlineData(typeof(int), true)] + [InlineData(typeof(uint), true)] + [InlineData(typeof(long), true)] + [InlineData(typeof(ulong), true)] + [InlineData(typeof(Int128), true)] + [InlineData(typeof(UInt128), true)] + [InlineData(typeof(BigInteger), true)] + [InlineData(typeof(float), true)] + [InlineData(typeof(double), true)] + [InlineData(typeof(Half), true)] + [InlineData(typeof(decimal), true)] + public void Test_IsNumericType(Type type, bool expectedResult) { - typeof(string).IsNumericType().ShouldBe(false); - typeof(char).IsNumericType().ShouldBe(false); - - typeof(byte).IsNumericType().ShouldBe(true); - typeof(sbyte).IsNumericType().ShouldBe(true); - typeof(short).IsNumericType().ShouldBe(true); - typeof(ushort).IsNumericType().ShouldBe(true); - typeof(int).IsNumericType().ShouldBe(true); - typeof(uint).IsNumericType().ShouldBe(true); - typeof(long).IsNumericType().ShouldBe(true); - typeof(ulong).IsNumericType().ShouldBe(true); - - typeof(float).IsNumericType().ShouldBe(true); - typeof(double).IsNumericType().ShouldBe(true); - typeof(decimal).IsNumericType().ShouldBe(true); - - typeof(BigInteger).IsNumericType().ShouldBe(true); + type.IsNumericType().ShouldBe(expectedResult); } - [Fact] - public void Test_IsNumericIntegerType() + [Theory] + [InlineData(typeof(string), false)] + [InlineData(typeof(char), false)] + [InlineData(typeof(bool), false)] + [InlineData(typeof(IntPtr), false)] + [InlineData(typeof(UIntPtr), false)] + [InlineData(typeof(byte), true)] + [InlineData(typeof(sbyte), true)] + [InlineData(typeof(short), true)] + [InlineData(typeof(ushort), true)] + [InlineData(typeof(int), true)] + [InlineData(typeof(uint), true)] + [InlineData(typeof(long), true)] + [InlineData(typeof(ulong), true)] + [InlineData(typeof(Int128), true)] + [InlineData(typeof(UInt128), true)] + [InlineData(typeof(BigInteger), true)] + [InlineData(typeof(float), false)] + [InlineData(typeof(double), false)] + [InlineData(typeof(Half), false)] + [InlineData(typeof(decimal), false)] + public void Test_IsNumericIntegerType(Type type, bool expectedResult) { - typeof(string).IsNumericIntegerType().ShouldBe(false); - typeof(char).IsNumericIntegerType().ShouldBe(false); - - typeof(byte).IsNumericIntegerType().ShouldBe(true); - typeof(sbyte).IsNumericIntegerType().ShouldBe(true); - typeof(short).IsNumericIntegerType().ShouldBe(true); - typeof(ushort).IsNumericIntegerType().ShouldBe(true); - typeof(int).IsNumericIntegerType().ShouldBe(true); - typeof(uint).IsNumericIntegerType().ShouldBe(true); - typeof(long).IsNumericIntegerType().ShouldBe(true); - typeof(ulong).IsNumericIntegerType().ShouldBe(true); - - typeof(float).IsNumericIntegerType().ShouldBe(false); - typeof(double).IsNumericIntegerType().ShouldBe(false); - typeof(decimal).IsNumericIntegerType().ShouldBe(false); - - typeof(BigInteger).IsNumericIntegerType().ShouldBe(true); + type.IsNumericIntegerType().ShouldBe(expectedResult); } - [Fact] - public void Test_IsNumericFloatType() + [Theory] + [InlineData(typeof(string), false)] + [InlineData(typeof(char), false)] + [InlineData(typeof(bool), false)] + [InlineData(typeof(IntPtr), false)] + [InlineData(typeof(UIntPtr), false)] + [InlineData(typeof(byte), false)] + [InlineData(typeof(sbyte), false)] + [InlineData(typeof(short), false)] + [InlineData(typeof(ushort), false)] + [InlineData(typeof(int), false)] + [InlineData(typeof(uint), false)] + [InlineData(typeof(long), false)] + [InlineData(typeof(ulong), false)] + [InlineData(typeof(Int128), false)] + [InlineData(typeof(UInt128), false)] + [InlineData(typeof(BigInteger), false)] + [InlineData(typeof(float), true)] + [InlineData(typeof(double), true)] + [InlineData(typeof(Half), true)] + [InlineData(typeof(decimal), true)] + public void Test_IsNumericFloatType(Type type, bool expectedResult) { - typeof(string).IsNumericFloatType().ShouldBe(false); - typeof(char).IsNumericFloatType().ShouldBe(false); - - typeof(byte).IsNumericFloatType().ShouldBe(false); - typeof(sbyte).IsNumericFloatType().ShouldBe(false); - typeof(short).IsNumericFloatType().ShouldBe(false); - typeof(ushort).IsNumericFloatType().ShouldBe(false); - typeof(int).IsNumericFloatType().ShouldBe(false); - typeof(uint).IsNumericFloatType().ShouldBe(false); - typeof(long).IsNumericFloatType().ShouldBe(false); - typeof(ulong).IsNumericFloatType().ShouldBe(false); - - typeof(float).IsNumericFloatType().ShouldBe(true); - typeof(double).IsNumericFloatType().ShouldBe(true); - typeof(decimal).IsNumericFloatType().ShouldBe(true); - - typeof(BigInteger).IsNumericFloatType().ShouldBe(false); + type.IsNumericFloatType().ShouldBe(expectedResult); } [Fact]