Проверка, является ли объект числом в C#


Я хотел бы проверить, является ли объект числом, так что .ToString() приведет к строке, содержащей цифры и +,-,.

можно ли просто проверить тип в .net (например:if (p is Number))?

или я должен преобразовать в строку, а затем попробовать парсинг удвоить?

обновление: чтобы уточнить мой объект-это int, uint, float, double и т. д. Это не строка. Я пытаюсь сделать функцию, которая бы сериализовать любой объект в XML вот так:

<string>content</string>

или

<numeric>123.3</numeric>

или вызвать исключение.

10 73

10 ответов:

вам просто нужно будет сделать проверку типа для каждого из основных числовых типов.

вот метод расширения, который должен выполнять эту работу:

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 / чем-то еще.

принято от Скотт Хансельман в своем блоге:

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

воспользуйтесь свойством 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 () поля типы значений. Также включено исправление для нулевых значений.

есть некоторые большие ответы. Вот решение "все-в-одном". Три перегрузки для разных обстоятельств.

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

вместо того, чтобы сворачивать свой собственный, самый надежный способ узнать, является ли встроенный тип числовым, вероятно, для ссылки Microsoft.VisualBasic и звонок Information.IsNumeric(object value). Реализация обрабатывает ряд тонких случаев, таких как char[] и шестнадцатеричные и окт строки.

там есть три разных понятия:

  • чтобы проверить, если это и число (т. е. (обычно в коробке) само числовое значение), проверьте тип с is - например,if(obj is int) {...}
  • чтобы проверить, может ли строка быть проанализирована как число; используйте TryParse()
  • но если объект не является числом или строкой, но вы подозреваете ToString() может дать то, что выглядит как число, то вызов ToString() и рассматривать его как строку

в первых двух случаях, вам, вероятно, придется обрабатывать отдельно каждый числовой тип вы хотите поддержать (double/decimal/int) - каждый из них имеет различные диапазоны и точность, например.

вы также можете посмотреть на регулярное выражение для быстрой грубой проверки.

Предположим ваш входной строки...

есть 2 способа:

использовать двойные.TryParse ()

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

использовать регулярное выражение

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

Да, это работает:

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

для числа с плавающей запятой вам нужно будет проверить с помощью типа float:

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

вы можете использовать такой код:

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

Если ваш объект является строкой, это не будет разбирать строку. Однако, если ваш объект является Int32, Single, Double и т. д. он будет выполнять преобразование.

Если ваше требование действительно

.ToString () приведет к строке содержит цифры и+, -,.

и вы хотите использовать double.TryParse затем вам нужно использовать перегрузку, которая принимает параметр NumberStyles, и убедитесь, что вы используете инвариантный язык и региональные параметры.

например, для числа, которое может иметь начальный знак, без ведущих или конечных пробелов, без разделителя тысяч и десятичного разделителя периода, использование:

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