개체가 C #에서 숫자인지 확인


89

나는 그 때문에 물체가 숫자인지 확인하고 싶습니다 .ToString()숫자를 포함하고 문자열 초래 +, -,.

.net (예 :)에서 간단한 유형 검사로 가능 if (p is Number)합니까?

아니면 문자열로 변환 한 다음 double로 구문 분석해야합니까?

업데이트 : 내 개체가 int, uint, float, double 등임을 명확히하기 위해 문자열이 아닙니다. 다음과 같이 모든 개체를 xml로 직렬화하는 함수를 만들려고합니다.

<string>content</string>

또는

<numeric>123.3</numeric>

또는 예외를 발생시킵니다.


5
당신 같은 소리는 특정 .NET으로 한 공급자 무엇이 잘못되었는지 자신의 XmlSerializer- 쓰기를 시도 msdn.microsoft.com/en-us/library/...를 ?
RichardOD

2
XSD를 사용하여 XML 형식을 정의한 다음 제공된 XSD 도구 ( msdn.microsoft.com/en-us/library/x6c1kb0s)를
Dexter

@RichardOD : xml 직렬화를 사용하여 object []를 직렬화 할 수 있습니까? Flash 함수 adobe.com/livedocs/flex/201/html/wwhelp/wwhimpl/common/html/…
Piotr Czapla

답변:


181

각 기본 숫자 유형에 대해 유형 검사를 수행하기 만하면됩니다.

작업을 수행해야하는 확장 메서드는 다음과 같습니다.

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;
}

이것은 모든 숫자 유형을 포함해야합니다.

최신 정보

실제로 deserialization 중에 문자열에서 숫자를 구문 분석하려는 것 같습니다. 이 경우를 사용하는 것이 가장 좋습니다 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/ 다른 것에 추가 호출을 추가해야합니다 .


내 목적은 숫자입니다 INT, 짧은, UINT, 플로트, 더블 또는 다른 것입니다
표트르 Czapla

@Piotr : 아 맞다. 내가 당신을 오해 한 것 같습니다. 업데이트 된 답변을 참조하십시오.
Noldorin

1
@Noldorin : 실제로 이전 버전의 코드도 작동합니다. null 검사를 추가하고 value.ToString ()을 사용하십시오. 그러면 모든 숫자 유형을 확인할 필요가 없습니다.
Fredrik Mörk

1
. 적합한 솔루션이 그 자세한 :(입니다 그것은 슬픈이다 @Noldorin
표트르 Czapla

1
@Joe : 사실, ToString도 현재 문화를 사용하기 때문에 차이를 만들지 않습니다.
Noldorin

36

Scott Hanselman의 블로그 에서 발췌 :

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);
}

6
이 접근 방식의 문제는 숫자처럼 보이는 문자열을 전달하면 형식이 지정된다는 것입니다. 대부분의 사람들에게는 괜찮을지 모르지만 나에게는 쇼 스토퍼였습니다.
Rob Sedgwick

1
이것에 대한 또 다른 잠재적 인 문제는 double에 대한 최소 / 최대 값을 구문 분석 할 수 없다는 것입니다. double.Parse(double.MaxValue.ToString())됩니다 OverflowException. .ToString("R")이 경우 왕복 수정자를 제공하여이 문제를 해결할 수 있지만 Convert.ToString(...)유형을 모르기 때문에 해당 오버로드를 사용할 수 없습니다. 나는 이것이 약간의 부수적 인 경우라는 것을 알고 있지만 내 자신의 .IsNumeric()확장에 대한 테스트를 작성하는 동안 우연히 발견되었습니다 . 내 "솔루션"은 구문 분석을 시도하기 전에 유형 검사 swtich를 추가하는 것이 었습니다. 코드에 대한이 질문에 대한 내 대답을 참조하십시오.

21

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 () 상자 값 유형 이후 제네릭이 제거되었습니다. nullable 값에 대한 수정도 포함되었습니다.


1
제네릭 부분은 여기에 추가 정보를 제공하지 않습니까? 객체로 볼 수 있습니다 당신 전용 액세스 GetType을 () ...
피터 Lillevold

값 유형에 대해 호출되면 하나의 상자 작업을 저장합니다. 재사용 가능성을 생각하십시오.
Kenan EK

1
obj.GetType 대신 typeof (T)를 사용하지 않는 이유는 누군가가 null 참조 유형을 전달하는 경우 NullReferenceException이 발생하지 않는 방식입니다. 값 유형 만 허용하도록 T에 일반 제한을 둘 수도 있습니다. 물론 그렇게한다면 컴파일 타임에 많은 정보를 얻기 시작합니다.
Trillian

objectstring기본 유형이 아니다.
We Are All Monica

@jnylen :이 대답은 꽤 오래 전이었습니다. 나는 그 당시에 반사 된 프레임 워크 소스에서 무언가를 찾았다 고 생각하지만, 오늘 누가 말할 수 있는지 ... 고정 된 대답.
Kenan EK

10

위에 몇 가지 훌륭한 답변이 있습니다. 다음은 올인원 솔루션입니다. 다른 상황에 대한 세 가지 과부하.

// 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)); }

널 (null) 검사를 추가하는 것을 고려
wiero

실제로 null 검사가 필요하지 않습니다. 확장 메서드로서 null 값으로 호출 할 수 없습니다. 물론 누군가는 여전히 일반 함수로 호출 할 수 있지만 확장 메서드의 예상되는 사용은 아닙니다.
믹 브루노

5
null 값으로 호출 할 수 있다고 생각합니다. 객체 obj = null; obj.IsNumeric ();
wiero

감사합니다 Weiro, 수정했습니다. null 값으로 확장 메서드를 호출하는 것이 가능하다는 것을 알지 못했지만 물론 가능합니다!
Mick Bruno

; "복귀 (? ISNUMERIC (x.GetType ()) x는 == null이 거짓)"나는 처음 과부하가 마지막에 괄호가 누락 생각
글렌 슨

8

자체적으로 롤링하는 대신 내장 유형이 숫자인지 확인하는 가장 안정적인 방법은를 참조 Microsoft.VisualBasic하고 호출하는 것 Information.IsNumeric(object value)입니다. 구현은 char[]및 HEX 및 OCT 문자열과 같은 여러 가지 미묘한 경우를 처리합니다 .


이것은 맨 위에 있어야합니다!
nawfal

4

세 가지 다른 개념이 있습니다.

  • 이 있는지 확인하는 것이다 숫자 (즉, (일반적으로 박스형) 수치 값 자체)와 타입을 확인 is- 예를 들어if(obj is int) {...}
  • 문자열이 숫자로 구문 분석 될 수 있는지 확인합니다. 사용하다TryParse()
  • 그러나 객체가 숫자 나 문자열이 아니지만 숫자처럼 보이는ToString() 것을 줄 수 있다고 의심되는 경우 호출 하여 문자열로 취급합니다. ToString()

처음 두 경우 모두 지원하려는 각 숫자 유형 ( double/ decimal/ int) 을 개별적으로 처리해야 할 것입니다 . 예를 들어 각각 다른 범위와 정확도를가집니다.

빠른 대략적인 확인을 위해 정규식을 볼 수도 있습니다.


4

입력이 문자열이라고 가정합니다 ...

두 가지 방법이 있습니다.

Double.TryParse () 사용

double temp;
bool isNumber = Double.TryParse(input, out temp);

정규식 사용

 bool isNumber = Regex.IsMatch(input,@"-?\d+(\.\d+)?");

4

다음과 같은 코드를 사용할 수 있습니다.

if (n is IConvertible)
  return ((IConvertible) n).ToDouble(CultureInfo.CurrentCulture);
else
  // Cannot be converted.

개체가 인 경우 Int32, Single, Double등이 변환을 수행합니다. 또한 문자열이 구현 IConvertible되지만 문자열이 double로 변환되지 않으면 a FormatException가 발생합니다.


실제로 문자열은 구문 분석되지만 올바른 형식이 아닌 경우 FormatException이 발생합니다.
alfoks

@alfoks : 당신이 절대적으로 옳으므로 대답을 업데이트했습니다.
Martin Liversage 2010 년

1

귀하의 요구 사항이 정말

.ToString ()은 숫자와 +,-,를 포함하는 문자열을 생성합니다.

double.TryParse를 사용하려면 NumberStyles 매개 변수를 사용하는 오버로드를 사용해야하며 고정 문화권을 사용하고 있는지 확인해야합니다.

예를 들어 선행 기호, 선행 또는 후행 공백 없음, 천 단위 구분 기호 및 마침표 소수 구분 기호가있는 숫자의 경우 다음을 사용하십시오.

NumberStyles style = 
   NumberStyles.AllowLeadingSign | 
   NumberStyles.AllowDecimalPoint | 
double.TryParse(input, style, CultureInfo.InvariantCulture, out result);

1

object.IsNumeric()이 질문에 대한 Saul Dolgin의 답변을 기반으로 내 자신의 확장 방법을 작성하는 동안 나는 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 _);
}

nullable 형식에주의하십시오.
Guillermo Prandi

0

예, 작동합니다.

object x = 1;
Assert.That(x is int);

부동 소수점 숫자의 경우 float 유형을 사용하여 테스트해야합니다.

object x = 1f;
Assert.That(x is float);

이는 객체가 암시 적으로 또는 명시 적으로 객체로 캐스팅되기 전에 int 인 경우 작동합니다. 귀하의 예에서 매직 넘버 1은 int이고 변수 x의 유형으로 캐스트됩니다. 객체 x = 1.0을 수행했다면 어설 션이 false를 반환했을 것입니다.
Dexter

정수가 아닌 숫자가 있습니다.
Fredrik Mörk

예, 내 요점은 기본적으로 @Noldorin이 현재 답변에서 가지고있는 것입니다.
Peter Lillevold
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.