4

When using reflection I thought type.IsPrimitive would be enough to tell me if it was a number, however that turned out to be wrong. Decimal is not a primitive type.

Without typing out a long list of types of numbers like Int64,Int32,Int16,UInt64, etc. How would one go around determining if a particular object is a number? I feel there is an easier way to do this other than listing out all the types and comparing them to the type in question.

One step further, how do I tell if a number is a whole number or contains decimals, but isn't something like Bool? I guess I would like a reflection extension for IsNumeric,IsWholeNumber, and IsFloatingPoint, but they don't exist to my knowledge.

EDIT :

I don't agree with marked as duplicate because the solution uses a list\case statement to find out whether it is a number. I do want to know if there exists a better solution since the answer(s) are > 3 years old.

UPDATE :

If anyone else is searching for this, I made an extension library based on the accepted answer for this "duplicate question". Hope this helps.

namespace HelperLibrary.Extensions
{
    /// <summary>
    /// Extensions for the Type class.
    /// </summary>
    public static class TypeExtensions
    {
        /// <summary>
        /// Gets a value indicating whether the current System.Type is represented in a numeric format.
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsNumeric(this Type type)
        {
            if (type == null)
            {
                return false;
            }
            var typeCode = Type.GetTypeCode(type);
            switch (typeCode)
            {
                case TypeCode.Byte:
                case TypeCode.Decimal:
                case TypeCode.Double:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                case TypeCode.Single:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                    return true;
                //case TypeCode.Char: cannot resolve without object value
                //case TypeCode.String: cannot resolve without object value
                case TypeCode.Object:
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        return IsNumeric(Nullable.GetUnderlyingType(type));
                    }
                    return false;
                default:
                    return false;
            }
        }

        /// <summary>
        /// Gets a value indicating whether the current System.Type is a floating point number.
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsFloatingPoint(this Type type)
        {
            if (type == null)
            {
                return false;
            }

            var typeCode = Type.GetTypeCode(type);
            switch (typeCode)
            {
                case TypeCode.Decimal:
                case TypeCode.Double:
                case TypeCode.Single:
                    return true;
                //case TypeCode.String: cannot resolve without object value
                case TypeCode.Object:
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        return IsFloatingPoint(Nullable.GetUnderlyingType(type));
                    }
                    return false;
                default:
                    return false;
            }
        }

        /// <summary>
        /// Gets a value indicating whether the current System.Type is a whole number.
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsWholeNumber(this Type type)
        {
            if (type == null)
            {
                return false;
            }

            var typeCode = Type.GetTypeCode(type);
            switch (typeCode)
            {
                case TypeCode.Byte:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.SByte:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                    return true;
                //case TypeCode.Char: cannot resolve without object value
                //case TypeCode.String: cannot resolve without object value
                case TypeCode.Object:
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        return IsWholeNumber(Nullable.GetUnderlyingType(type));
                    }
                    return false;
                default:
                    return false;
            }
        }
    }
}
Jim Stahl
  • 93
  • 1
  • 5
  • @Lee - True. Hmm... Was thinking too much about `byte[]` in terms as its usage in a byte array instead of `byte` as an 8-bit number. I'll edit. – Jim Stahl Jun 25 '14 at 20:00
  • Regarding your edit: in what way specifically are you looking for a better option than a tested solution in 30 lines of code? It hasn't been built into the framework as far as I know. – CodeCaster Jun 25 '14 at 20:09
  • 1
    @CodeCaster - Hmmm, well I guess I am out of luck then. I was hoping I was overlooking some useful open source library or usage of reflection. I'll roll my own then! – Jim Stahl Jun 25 '14 at 20:13

0 Answers0