我想检查某个对象是否为数字,以便.ToString()
生成包含数字的字符串+
,-
,.
是否可以通过.net中的简单类型检查(如:if (p is Number)
)?
或者我应该转换为字符串,然后尝试解析为双倍?
更新:为了澄清我的对象是int,uint,float,double等等,它不是一个字符串。 我正在尝试创建一个将任何对象序列化为xml的函数,如下所示:
<string>content</string>
或
<numeric>123.3</numeric>
或提出异常。
答案 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)
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.
如果您的对象是Int32
,Single
,Double
等,则会执行转换。此外,字符串实现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.MaxValue
或double.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 _);
}