C#'s Type object does not have an IsNumeric method or property. Fortunately, it is easy to create an extension method to do this. While there are many approachies using TypeCodes to do this, this will not garuntee support for .Net types.
To create an extension method, create a static partial class with static methods. The method body consists of looking within the NumericTypes HashSet for the passed type. An IsNumericType method can be created for an general object using an expression body.
public static partial class TypeExtensions
{
/// <summary>
/// The numeric types
/// </summary>
public static readonly HashSet<Type> NumericTypes = new HashSet<Type>()
{
typeof(byte), typeof(sbyte),
typeof(int), typeof(uint),
typeof(UInt16), typeof(UInt32), typeof(UInt64),
typeof(Int16), typeof(Int32), typeof(Int64),
typeof(long), typeof(ulong),
typeof(short), typeof(ushort),
typeof(float),
typeof(Single),
typeof(double),
typeof(Double),
typeof(decimal),
typeof(Decimal),
// Support for .Net types
typeof(BigInteger), typeof(Complex)
};
/// <summary>
/// Checks if the type is numeric.
/// </summary>
/// <param name="type">The type</param>
/// <returns>True if the type is numeric</returns>
public static bool IsNumeric(this Type type)
{
// Use the underlying type for nullable numeric types
while (!NumericTypes.Contains(type) &&
Type.GetTypeCode(type) == TypeCode.Object &&
type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = Nullable.GetUnderlyingType(type);
}
return NumericTypes.Contains(type);
}
/// <summary>
/// Determines if an object is of a numeric type.
/// </summary>
/// <param name="obj">The object.</param>
/// <returns>True if the object's type is numeric</returns>
public static bool IsNumericType(this object obj)
=> obj != null && obj.GetType().IsNumeric();
}
The above code will require a using statement of the extension methods' namespace to be able to perform the evaluation. To test the result of the evaluation, a series of unit tests may be performed as an example.
[TestClass]
public class TypeExtensionsTests
{
[TestMethod]
public void IsNumericBasicTests()
{
int a = 1;
Assert.IsTrue(a.IsNumericType());
double b = 1.01;
Assert.IsTrue(b.IsNumericType());
float c = 1.01F;
Assert.IsTrue(c.IsNumericType());
// A string is not a numeric
string str = "This is a string";
Assert.IsFalse(str.IsNumericType());
}
[TestMethod]
public void IsNumericTestsForNullableTypes()
{
int? an = 1;
Assert.IsTrue(an.IsNumericType());
double? bn = 1.01;
Assert.IsTrue(bn.IsNumericType());
float? cn = 1.01F;
Assert.IsTrue(cn.IsNumericType());
}
[TestMethod]
public void IsNumericTestsForCollections()
{
// An array is not a numeric
int[] aa = new int[] { 1, 98, 2, 97, 3 };
Assert.IsFalse(aa.IsNumericType());
// A list is not a numeric
List<double> dl = new List<double> { 1.2, 98.7, 2.3, 97.8, 3.4 };
Assert.IsFalse(dl.IsNumericType());
// use of var should not change the behavior
var vl = new List<float?> { 1.2F, 98.7F, 2.3F, 97.8F, 3.4F };
Assert.IsFalse(vl.IsNumericType());
}
}