Проверка, является ли объект числом в C#
Я хотел бы проверить, является ли объект числом, так что .ToString() приведет к строке, содержащей цифры и +,-,.
можно ли просто проверить тип в .net (например:if (p is Number))?
или я должен преобразовать в строку, а затем попробовать парсинг удвоить?
обновление: чтобы уточнить мой объект-это int, uint, float, double и т. д. Это не строка. Я пытаюсь сделать функцию, которая бы сериализовать любой объект в XML вот так:
<string>content</string>
или
<numeric>123.3</numeric>
или вызвать исключение.
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);