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;
}
}
}
}