Я хотел бы проверить , если объект является числом , так что .ToString()
приведет к строке , содержащей цифры и +
, -
,.
Возможно ли это с помощью простой проверки типов в .net (например:) if (p is Number)
?
Или я должен преобразовать в строку, а затем попытаться выполнить синтаксический анализ в два раза?
Обновление: чтобы уточнить, что мой объект - это int, uint, float, double и т. Д., Это не строка. Я пытаюсь создать функцию, которая сериализует любой объект в xml следующим образом:
<string>content</string>
или
<numeric>123.3</numeric>
или создать исключение.
c#
.net
serialization
xml-serialization
Петр Чапла
источник
источник
Ответы:
Вам просто нужно будет выполнить проверку типа для каждого из основных числовых типов.
Вот метод расширения, который должен работать:
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); }
источник
double.Parse(double.MaxValue.ToString())
вызываетOverflowException
. Вы можете исправить это, указав.ToString("R")
в этом случае модификатор туда и обратно , но эта перегрузка недоступна,Convert.ToString(...)
поскольку мы не знаем тип. Я знаю, что это немного второстепенный случай, но я наткнулся на него, когда писал тесты для своего собственного.IsNumeric()
расширения. Мое «решение» заключалось в том, чтобы добавить переключатель проверки типов перед тем, как что-либо анализировать, см. Мой ответ на этот вопрос для кода.Воспользуйтесь свойством 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 (). Также включено исправление для значений, допускающих значение NULL.
источник
object
иstring
не являются примитивными типами.Выше есть несколько отличных ответов. Вот универсальное решение. Три перегрузки для разных обстоятельств.
// 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[]
строки HEX и OCT.источник
Здесь есть три разных концепции:
is
- например ,if(obj is int) {...}
TryParse()
ToString()
может дать что - то , что выглядит как число, то звонитьToString()
и рассматривать его как строкуВ обоих первых двух случаях вам, вероятно, придется отдельно обрабатывать каждый числовой тип, который вы хотите поддерживать (
double
/decimal
/int
) - например, каждый имеет разные диапазоны и точность.Вы также можете посмотреть на регулярное выражение для быстрой грубой проверки.
источник
Предполагая, что ваш ввод - это строка ...
Есть 2 способа:
используйте Double.TryParse ()
double temp; bool isNumber = Double.TryParse(input, out temp);
использовать Regex
bool isNumber = Regex.IsMatch(input,@"-?\d+(\.\d+)?");
источник
Вы можете использовать такой код:
if (n is IConvertible) return ((IConvertible) n).ToDouble(CultureInfo.CurrentCulture); else // Cannot be converted.
Если объект является
Int32
,Single
, иDouble
т.д. он будет выполнять преобразование. Кроме того, реализуется строка,IConvertible
но если строка не может быть преобразована в двойную, тоFormatException
будет выбрано.источник
Если ваше требование действительно
и вы хотите использовать double.TryParse, тогда вам нужно использовать перегрузку, которая принимает параметр NumberStyles, и убедитесь, что вы используете инвариантную культуру.
Например, для числа, которое может иметь начальный знак, без начальных или конечных пробелов, без разделителя тысяч и десятичного разделителя с точкой, используйте:
NumberStyles style = NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | double.TryParse(input, style, CultureInfo.InvariantCulture, out result);
источник
При написании моего собственного
object.IsNumeric()
метода расширения, основанного на ответе Сола Долгина на этот вопрос, я столкнулся с потенциальной проблемой, заключающейся в том, что вы получите сообщение,OverflowException
если попробуете его с помощьюdouble.MaxValue
илиdouble.MinValue
.Мое «решение» заключалось в том, чтобы объединить принятый ответ от Нолдорина с ответом Саула Долгина и добавить переключатель сопоставления с образцом, прежде чем пытаться что-либо проанализировать (и использовать некоторую доброту 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 _); }
источник
Да, это работает:
object x = 1; Assert.That(x is int);
Для числа с плавающей запятой вам нужно будет протестировать, используя тип float:
object x = 1f; Assert.That(x is float);
источник