.ToString()
が数字と_+
_、_-
_、_.
_を含む文字列になるように、オブジェクトが数値であるかどうかを確認したい
.netでの単純な型チェックによって可能ですか(例:if (p is Number)
)?
または、文字列に変換してから、二重に解析してみますか?
更新:私のオブジェクトがint、uint、float、doubleなどであることを明確にするために、それは文字列ではありません。私は次のようにオブジェクトをXMLにシリアル化する関数を作成しようとしています:
_<string>content</string>
_
または
_<numeric>123.3</numeric>
_
または例外を発生させます。
基本的な数値型ごとに型チェックを行うだけです。
これを行う拡張メソッドは次のとおりです。
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()は値の型をボックス化するため、ジェネリックは削除されました。 null許容値の修正も含まれています。
上記のいくつかの素晴らしい答えがあります。これがオールインワンソリューションです。さまざまな状況の3つのオーバーロード。
// 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文字列などの多くの微妙なケースを処理します。
そこには3つの異なる概念があります。
is
を使用してタイプを確認します。たとえば、if(obj is int) {...}
TryParse()
を使用しますToString()
が数字のようなlooksを与えると思われる場合、それからcallToString()
を文字列として扱います最初の2つの場合の両方で、サポートする各数値型を個別に処理する必要があります(double
/decimal
/int
)-それぞれ異なる範囲を持ち、たとえば、精度。
また、簡単な大まかなチェックのために正規表現を見ることができます。
入力が文字列であると仮定します...
2つの方法があります。
double.TryParse()を使用します
double temp;
bool isNumber = Double.TryParse(input, out temp);
正規表現を使用する
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
を実装しますが、文字列がdoubleに変換できない場合、FormatException
がスローされます。
あなたの要件が本当に
.ToString()は、数字と+、-、を含む文字列になります。
double.TryParseを使用する場合は、NumberStylesパラメーターを受け取るオーバーロードを使用し、インバリアントカルチャを使用していることを確認する必要があります。
たとえば、先頭に符号があり、先頭または末尾に空白がなく、千単位の区切り記号とピリオドの小数点記号がない数値の場合、次を使用します。
NumberStyles style =
NumberStyles.AllowLeadingSign |
NumberStyles.AllowDecimalPoint |
double.TryParse(input, style, CultureInfo.InvariantCulture, out result);
この質問に対するSaul Dolginの答えに基づいて独自のobject.IsNumeric()
拡張メソッドを作成しているときに、double.MaxValue
で試してみるとOverflowException
を取得するという潜在的な問題に遭遇しました。 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);