C# - how to determine whether a Type is a number

后端 未结 18 2302
傲寒
傲寒 2020-11-28 22:47

Is there a way to determine whether or not a given .Net Type is a number? For example: System.UInt32/UInt16/Double are all numbers. I want to avoid a long switc

18条回答
  •  青春惊慌失措
    2020-11-28 23:23

    With C# 7 this method gives to me better performance than switch case on TypeCode and HashSet:

    public static bool IsNumeric(this object o) => o is byte || o is sbyte || o is ushort || o is uint || o is ulong || o is short || o is int || o is long || o is float || o is double || o is decimal;
    

    Tests are following:

    public static class Extensions
    {
        public static HashSet NumericTypes = new HashSet()
        {
            typeof(byte), typeof(sbyte), typeof(ushort), typeof(uint), typeof(ulong), typeof(short), typeof(int), typeof(long), typeof(decimal), typeof(double), typeof(float)
        };
    
        public static bool IsNumeric1(this object o) => NumericTypes.Contains(o.GetType());
    
        public static bool IsNumeric2(this object o) => o is byte || o is sbyte || o is ushort || o is uint || o is ulong || o is short || o is int || o is long || o is decimal || o is double || o is float;
    
        public static bool IsNumeric3(this object o)
        {
            switch (o)
            {
                case Byte b:
                case SByte sb:
                case UInt16 u16:
                case UInt32 u32:
                case UInt64 u64:
                case Int16 i16:
                case Int32 i32:
                case Int64 i64:
                case Decimal m:
                case Double d:
                case Single f:
                    return true;
                default:
                    return false;
            }
        }
    
        public static bool IsNumeric4(this object o)
        {
            switch (Type.GetTypeCode(o.GetType()))
            {
                case TypeCode.Byte:
                case TypeCode.SByte:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.Decimal:
                case TypeCode.Double:
                case TypeCode.Single:
                    return true;
                default:
                    return false;
            }
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {           
            var count = 100000000;
    
            //warm up calls
            for (var i = 0; i < count; i++)
            {
                i.IsNumeric1();
            }
            for (var i = 0; i < count; i++)
            {
                i.IsNumeric2();
            }
            for (var i = 0; i < count; i++)
            {
                i.IsNumeric3();
            }
            for (var i = 0; i < count; i++)
            {
                i.IsNumeric4();
            }
    
            //Tests begin here
            var sw = new Stopwatch();
            sw.Restart();
            for (var i = 0; i < count; i++)
            {
                i.IsNumeric1();
            }
            sw.Stop();
    
            Debug.WriteLine(sw.ElapsedMilliseconds);
    
            sw.Restart();
            for (var i = 0; i < count; i++)
            {
                i.IsNumeric2();
            }
            sw.Stop();
    
            Debug.WriteLine(sw.ElapsedMilliseconds);
    
            sw.Restart();
            for (var i = 0; i < count; i++)
            {
                i.IsNumeric3();
            }
            sw.Stop();
    
            Debug.WriteLine(sw.ElapsedMilliseconds);
    
            sw.Restart();
            for (var i = 0; i < count; i++)
            {
                i.IsNumeric4();
            }
            sw.Stop();
    
            Debug.WriteLine(sw.ElapsedMilliseconds);
        }
    

提交回复
热议问题