C# - 如何确定类型是否为数字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1749966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 20:28:54  来源:igfitidea点击:

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

c#.nettypes

提问by Adi Barda

Is there a way to determine whether or not a given .Net Type is a number? For example: System.UInt32/UInt16/Doubleare all numbers. I want to avoid a long switch-case on the Type.FullName.

有没有办法确定给定的 .Net 类型是否是数字?例如:System.UInt32/UInt16/Double都是数字。我想避免在Type.FullName.

采纳答案by Philip Wallace

Try this:

尝试这个:

Type type = object.GetType();
bool isNumber = (type.IsPrimitiveImple && type != typeof(bool) && type != typeof(char));
Type type = object.GetType();
bool isNumber = (type.IsPrimitiveImple && type != typeof(bool) && type != typeof(char));

The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Char, Double,and Single.

基本类型是 Boolean、Byte、SByte、Int16、UInt16、Int32、UInt32、Int64、UInt64、Char、Double 和 Single。

Taking Guillaume's solutiona little further:

更进一步地考虑Guillaume 的解决方案

public static bool IsNumericType(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;
  }
}

Usage:

用法:

int i = 32;
i.IsNumericType(); // True

string s = "Hello World";
s.IsNumericType(); // False

回答by Konamiman

You could use Type.IsPrimitiveand then sort out the Booleanand Chartypes, something like this:

您可以使用Type.IsPrimitive然后整理出BooleanChar类型,如下所示:

bool IsNumeric(Type type)
{
    return type.IsPrimitive && type!=typeof(char) && type!=typeof(bool);
}

EDIT: You may want to exclude the IntPtrand UIntPtrtypes as well, if you don't consider them to be numeric.

编辑:如果您不认为它们是数字,您可能还想排除IntPtrUIntPtr类型。

回答by Darin Dimitrov

Unfortunately these types don't have much in common other than they are all value types. But to avoid a long switch-case you could just define a readonly list with all these types and then just check if the given type is inside the list.

不幸的是,除了它们都是值类型之外,这些类型没有太多共同点。但是为了避免长时间的 switch-case,你可以定义一个包含所有这些类型的只读列表,然后检查给定的类型是否在列表中。

回答by Jon Skeet

Don't use a switch - just use a set:

不要使用开关 - 只需使用一组:

HashSet<Type> NumericTypes = new HashSet<Type>
{
    typeof(decimal), typeof(byte), typeof(sbyte),
    typeof(short), typeof(ushort), ...
};

EDIT: One advantage of this over using a type code is that when new numeric types are introduced into .NET (e.g. BigIntegerand Complex) it's easy to adjust - whereas those types won'tget a type code.

编辑:与使用类型代码相比,这样做的一个优点是,当将新的数字类型引入 .NET(例如BigIntegerComplex)时,它很容易调整 - 而这些类型不会获得类型代码。

回答by Craig

Short answer: No.

简短的回答:没有。

Longer Answer: Nope.

更长的答案:不。

The fact is that many different types in C# can contain numeric data. Unless you know what to expect (Int, Double, etc) you need to use the "long" case statement.

事实上,C# 中的许多不同类型都可以包含数字数据。除非您知道会发生什么(Int、Double 等),否则您需要使用“long”case 语句。

回答by johnny g

oops! Misread the question! Personally, would roll with Skeet's.

哎呀!看错问题了!就个人而言,会和飞碟一起滚动。



hrm, sounds like you want to DoSomethingon Typeof your data. What you could do is the following

人力资源管理,像你的声音要DoSomethingType您的数据。你可以做的是以下

public class MyClass
{
    private readonly Dictionary<Type, Func<SomeResult, object>> _map = 
        new Dictionary<Type, Func<SomeResult, object>> ();

    public MyClass ()
    {
        _map.Add (typeof (int), o => return SomeTypeSafeMethod ((int)(o)));
    }

    public SomeResult DoSomething<T>(T numericValue)
    {
        Type valueType = typeof (T);
        if (!_map.Contains (valueType))
        {
            throw new NotSupportedException (
                string.Format (
                "Does not support Type [{0}].", valueType.Name));
        }
        SomeResult result = _map[valueType] (numericValue);
        return result;
    }
}

回答by MandoMando

They are all value types (except for bool and maybe enum). So you could simply use:

它们都是值类型(bool 和 enum 除外)。所以你可以简单地使用:

bool IsNumberic(object o)
{
    return (o is System.ValueType && !(o is System.Boolean) && !(o is System.Enum))
}

回答by Guillaume

public static bool IsNumericType(Type type)
{
  switch (Type.GetTypeCode(type))
  {
    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;
  }
}

Note about optimization removed (see enzi comments)And if you really want to optimize it (losing readability and some safety...):

关于优化删除的注意事项(见 enzi 评论)如果你真的想优化它(失去可读性和一些安全性......):

public static bool IsNumericType(Type type)
{
  TypeCode typeCode = Type.GetTypeCode(type);
  //The TypeCode of numerical types are between SByte (5) and Decimal (15).
  return (int)typeCode >= 5 && (int)typeCode <= 15;
}
public static bool IsNumericType(Type type)
{
  TypeCode typeCode = Type.GetTypeCode(type);
  //The TypeCode of numerical types are between SByte (5) and Decimal (15).
  return (int)typeCode >= 5 && (int)typeCode <= 15;
}

回答by Jürgen Steinblock

None of the solutions takes Nullable into account.

没有一个解决方案将 Nullable 考虑在内。

I modified Jon Skeet's solution a bit:

我稍微修改了 Jon Skeet 的解决方案:

    private static HashSet<Type> NumericTypes = new HashSet<Type>
    {
        typeof(int),
        typeof(uint),
        typeof(double),
        typeof(decimal),
        ...
    };

    internal static bool IsNumericType(Type type)
    {
        return NumericTypes.Contains(type) ||
               NumericTypes.Contains(Nullable.GetUnderlyingType(type));
    }

I know I could just add the nullables itself to my HashSet. But this solution avoid the danger of forgetting to add a specific Nullable to your list.

我知道我可以将 nullables 本身添加到我的 HashSet 中。但是此解决方案避免了忘记将特定 Nullable 添加到列表中的危险。

    private static HashSet<Type> NumericTypes = new HashSet<Type>
    {
        typeof(int),
        typeof(int?),
        ...
    };

回答by cimnine

Approach based on Philip's proposal, enhanced with SFun28's inner type checkfor Nullabletypes:

基于Philip's proposal 的方法,通过SFun28 的内部类型检查增强了Nullable类型:

public static class IsNumericType
{
    public static bool IsNumeric(this Type type)
    {
        switch (Type.GetTypeCode(type))
        {
            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;
            case TypeCode.Object:
                if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    return Nullable.GetUnderlyingType(type).IsNumeric();
                    //return IsNumeric(Nullable.GetUnderlyingType(type));
                }
                return false;
            default:
                return false;
        }
    }
}

Why this? I had to check if a given Type typeis a numeric type, and not if an arbitrary object ois numeric.

为什么这个?我必须检查给定的Type type是否是数字类型,而不是任意的数字类型object o