检查对象是否是C#中的数字

时间:2009-07-15 10:50:09

标签: c# .net serialization xml-serialization

我想检查某个对象是否为数字,以便.ToString()生成包含数字的字符串+-.

是否可以通过.net中的简单类型检查(如:if (p is Number))?

或者我应该转换为字符串,然后尝试解析为双倍?

更新:为了澄清我的对象是int,uint,float,double等等,它不是一个字符串。 我正在尝试创建一个将任何对象序列化为xml的函数,如下所示:

<string>content</string>

<numeric>123.3</numeric>

或提出异常。

11 个答案:

答案 0 :(得分:160)

您只需要对每种基本数字类型进行类型检查。

这是一个应该完成工作的扩展方法:

public static bool IsNumber(this object value)
{
    return value is sbyte
            || value is byte
            || value is short
            || value is ushort
            || value is int
            || value is uint
            || value is long
            || value is ulong
            || value is float
            || value is double
            || value is decimal;
}

这应涵盖所有数字类型。

更新

在反序列化过程中,您确实希望解析字符串中的数字。在这种情况下,最好使用double.TryParse

string value = "123.3";
double num;
if (!double.TryParse(value, out num))
    throw new InvalidOperationException("Value is not a number.");

当然,这不会处理非常大的整数/长小数,但如果是这种情况,您只需要向long.TryParse / decimal.TryParse /其他任何内容添加其他调用。

答案 1 :(得分:34)

取自Scott Hanselman's Blog

public static bool IsNumeric(object expression)
{
    if (expression == null)
    return false;

    double number;
    return Double.TryParse( Convert.ToString( expression
                                            , CultureInfo.InvariantCulture)
                          , System.Globalization.NumberStyles.Any
                          , NumberFormatInfo.InvariantInfo
                          , out number);
}

答案 2 :(得分:18)

利用IsPrimitive属性制作一个方便的扩展方法:

public static bool IsNumber(this object obj)
{
    if (Equals(obj, null))
    {
        return false;
    }

    Type objType = obj.GetType();
    objType = Nullable.GetUnderlyingType(objType) ?? objType;

    if (objType.IsPrimitive)
    {
        return objType != typeof(bool) && 
            objType != typeof(char) && 
            objType != typeof(IntPtr) && 
            objType != typeof(UIntPtr);
    }

    return objType == typeof(decimal);
}

编辑:根据评论修正。 由于.GetType()框值类型,因此删除了泛型。还包括修复可以为空的值。

答案 3 :(得分:9)

上面有一些很好的答案。这是一个多功能的解决方案。针对不同情况的三次重载。

// Extension method, call for any object, eg "if (x.IsNumeric())..."
public static bool IsNumeric(this object x) { return (x==null ? false : IsNumeric(x.GetType())); }

// Method where you know the type of the object
public static bool IsNumeric(Type type) { return IsNumeric(type, Type.GetTypeCode(type)); }

// Method where you know the type and the type code of the object
public static bool IsNumeric(Type type, TypeCode typeCode) { return (typeCode == TypeCode.Decimal || (type.IsPrimitive && typeCode != TypeCode.Object && typeCode != TypeCode.Boolean && typeCode != TypeCode.Char)); }

答案 4 :(得分:7)

而不是滚动自己,最可靠的方法来判断内置类型是否为数字可能是引用Microsoft.VisualBasic并调用Information.IsNumeric(object value)。该实现处理许多细微的情况,例如char[]和HEX以及OCT字符串。

答案 5 :(得分:4)

有三种不同的概念:

  • 检查 是否为数字(即(通常为盒装)数字本身),请使用is检查类型 - 例如if(obj is int) {...}
  • 检查字符串是否可以解析为数字;使用TryParse()
  • 但是如果对象不是数字或字符串,但您怀疑ToString()可能会提供看起来像的内容,那么调用 { {1}}并将其视为字符串

在前两种情况下,您可能必须单独处理要支持的每种数字类型(ToString() / double / decimal) - 每种数据类型都有不同的范围,准确性,例如。

您还可以查看正则表达式进行快速粗略检查。

答案 6 :(得分:3)

假设您输入的是字符串......

有两种方式:

使用Double.TryParse()

double temp;
bool isNumber = Double.TryParse(input, out temp);

使用Regex

 bool isNumber = Regex.IsMatch(input,@"-?\d+(\.\d+)?");

答案 7 :(得分:2)

你可以使用这样的代码:

if (n is IConvertible)
  return ((IConvertible) n).ToDouble(CultureInfo.CurrentCulture);
else
  // Cannot be converted.

如果您的对象是Int32SingleDouble等,则会执行转换。此外,字符串实现IConvertible但如果字符串不可转换为double,则会抛出FormatException

答案 8 :(得分:1)

是的,这有效:

object x = 1;
Assert.That(x is int);

对于浮点数,您必须使用浮点类型进行测试:

object x = 1f;
Assert.That(x is float);

答案 9 :(得分:1)

如果您的要求确实是

  

.ToString()会产生一个字符串   包含数字和+, - ,。

并且您想使用double.TryParse然后您需要使用带有NumberStyles参数的重载,并确保您使用的是不变文化。

例如,对于可能具有前导符号,没有前导或尾随空格,没有千位分隔符和句点小数分隔符的数字,请使用:

NumberStyles style = 
   NumberStyles.AllowLeadingSign | 
   NumberStyles.AllowDecimalPoint | 
double.TryParse(input, style, CultureInfo.InvariantCulture, out result);

答案 10 :(得分:0)

在根据索尔·多尔金(Saul Dolgin)对这个问题的回答编写自己的object.IsNumeric()扩展方法时,我遇到了一个潜在问题,即如果您使用OverflowException尝试使用double.MaxValuedouble.MinValue

我的“解决方案”是将Noldorin接受的答案与Saul Dolgin的答案相结合,并在尝试解析任何内容之前添加模式匹配开关(并使用C#7的优点来整理一下):

public static bool IsNumeric(this object obj)
{
    if (obj == null) return false;

    switch (obj)
    {
        case sbyte _: return true;
        case byte _: return true;
        case short _: return true;
        case ushort _: return true;
        case int _: return true;
        case uint _: return true;
        case long _: return true;
        case ulong _: return true;
        case float _: return true;
        case double _: return true;
        case decimal _: return true;
    }

    string s = Convert.ToString(obj, CultureInfo.InvariantCulture);

    return double.TryParse(s, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out double _);
}