Проверка, является ли объект числом в 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);