c# - bool - 문자열을 nullable int로 구문 분석하는 방법




boolean (14)

C #에서 nullable int로 문자열을 구문 분석하고 싶습니다. 즉. 문자열의 int 값을 반환하거나 구문 분석 할 수없는 경우 null을 반환하려고합니다.

나는 이것이 일할 수 있기를 바랬다.

int? val = stringVal as int?;

하지만 그건 작동하지 않을 것입니다. 그래서 지금 제가하고있는 방식은이 확장 메소드를 작성한 것입니다.

public static int? ParseNullableInt(this string value)
{
    if (value == null || value.Trim() == string.Empty)
    {
        return null;
    }
    else
    {
        try
        {
            return int.Parse(value);
        }
        catch
        {
            return null;
        }
    }
}   

이 작업을 수행하는 더 좋은 방법이 있습니까?

편집 : TryParse 제안을 주셔서 감사합니다, 나는 그것에 대해 알았지 만 같은 일을했습니다. 더 nullable int로 직접 구문 분석 할 내장 된 프레임 워크 메서드가 있는지 알고 싶습니다.


더 nullable int로 직접 구문 분석 할 내장 된 프레임 워크 메서드가 있는지 알고 싶습니다.

존재하지 않는다.


Glenn Slaven : nullable int로 직접 파싱하는 기본 제공 프레임 워크 메서드가 있는지 알고 싶습니다.

값이 null 또는 빈 문자열처럼 유효하지만 유효하지 않은 값에 대한 예외를 throw하는 경우 nullable int (및 int가 아님)에 직접 구문 분석하는이 방법이 있으므로 예외를 catch하고 기본값을 반환해야합니다 그 상황을 위해 :

public static T Parse<T>(object value)
{
    try { return (T)System.ComponentModel.TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value.ToString()); }
    catch { return default(T); }
}

이 접근법은 Null을 허용 할 수있는 파싱뿐만 아니라 Null을 허용하지 않는 파싱에도 여전히 사용할 수 있습니다.

enum Fruit { Orange, Apple }
var res1 = Parse<Fruit>("Apple");
var res2 = Parse<Fruit?>("Banana");
var res3 = Parse<int?>("100") ?? 5; //use this for non-zero default
var res4 = Parse<Unit>("45%");

주의 : 예외를 캡처하는 대신 사용할 수있는 변환기에 IsValid 메서드가 있습니다 (throw 된 예외로 인해 예상 하지 못한 오버 헤드 가 발생 함). 불행히도 .NET 4 이후에만 작동하지만 올바른 DateTime 형식의 유효성을 검사 할 때 로캘을 확인하지 않는 문제가 여전히 있습니다 ( 버그 93559 참조).


나는 좀 더 일반적인 광산을 공유해야한다고 느꼈다.

용법:

var result = "123".ParseBy(int.Parse);

var result2 = "123".ParseBy<int>(int.TryParse);

해결책:

public static class NullableParse
{
    public static Nullable<T> ParseBy<T>(this string input, Func<string, T> parser)
        where T : struct
    {
        try
        {
            return parser(input);
        }
        catch (Exception exc)
        {
            return null;
        }
    }

    public delegate bool TryParseDelegate<T>(string input, out T result);

    public static Nullable<T> ParseBy<T>(this string input, TryParseDelegate<T> parser)
        where T : struct
    {
        T t;
        if (parser(input, out t)) return t;
        return null;
    }
}

첫 번째 버전은 try-catch가 필요하기 때문에 느리지 만 깨끗하게 보입니다. 잘못된 문자열로 여러 번 호출되지 않는다면 그렇게 중요하지 않습니다. 성능이 문제가되면 TryParse 메서드를 사용할 때 컴파일러에서 유추 할 수 없으므로 ParseBy의 형식 매개 변수를 지정해야합니다. Func <> 내에서 out 키워드를 사용할 수 없기 때문에 델리게이트를 정의해야했지만 적어도이 시간에는 컴파일러가 명시 적 인스턴스를 요구하지 않았습니다.

마지막으로 decimal, DateTime, Guid 등 다른 구조체와 함께 사용할 수 있습니다.


나는 코드 울부 짖는 소리를 제안한다. 변환 오류가 발생하면 예외없이 작업 할 수 있습니다.

public static class Utils {      
public static bool TryParse<Tin, Tout>(this Tin obj, Func<Tin, Tout> onConvert, Action<Tout> onFill, Action<Exception> onError) {
  Tout value = default(Tout);
  bool ret = true;
  try {
    value = onConvert(obj);
  }
  catch (Exception exc) {
    onError(exc);
    ret = false;
  }
  if (ret)
    onFill(value);
  return ret;
}

public static bool TryParse(this string str, Action<int?> onFill, Action<Exception> onError) {
  return Utils.TryParse(str
    , s => string.IsNullOrEmpty(s) ? null : (int?)int.Parse(s)
    , onFill
    , onError);
}
public static bool TryParse(this string str, Action<int> onFill, Action<Exception> onError) {
  return Utils.TryParse(str
    , s => int.Parse(s)
    , onFill
    , onError);
}
}

코드에서이 확장 메서드를 사용합니다 (person 클래스의 fill int? Age 속성).

string ageStr = AgeTextBox.Text;
Utils.TryParse(ageStr, i => person.Age = i, exc => { MessageBox.Show(exc.Message); });

또는

AgeTextBox.Text.TryParse(i => person.Age = i, exc => { MessageBox.Show(exc.Message); });

내 솔루션은 매우 깨끗하고 멋진 솔루션이라고 생각합니다.

public static T? NullableParse<T>(string s) where T : struct
{
    try
    {
        return (T)typeof(T).GetMethod("Parse", new[] {typeof(string)}).Invoke(null, new[] { s });
    }
    catch (Exception)
    {
        return null;
    }
}

이것은 generics 인수에 정적 메서드 "Parse (string)"만 있으면되는 일반 솔루션입니다. 숫자, 부울, 날짜 시간 등에서 작동합니다.


내 요구 사항을 만족하는이 하나를 생각해 냈다. (내 확장 메서드가 프레임 워크의 TryParse를 최대한 가깝게 에뮬레이트하려고했지만 try {} catch {} 블록을 사용하지 않고 컴파일러없이 프레임 워크 메서드 내에서 nullable 형식)

private static bool TryParseNullableInt(this string s, out int? result)
{
    int i;
    result = int.TryParse(s, out i) ? (int?)i : null;
    return result != null;
}

다음은 모든 struct 유형에 대해 작동해야합니다. MSDN 포럼의 Matt Manela가 작성한 코드를 기반으로합니다. Murph가 지적한 것처럼 Exception 처리는 Types 전용 TryParse 메서드를 사용하는 것보다 비쌀 수 있습니다.

        public static bool TryParseStruct<T>(this string value, out Nullable<T> result)
            where T: struct 
        {
            if (string.IsNullOrEmpty(value))
            {
                result = new Nullable<T>();

                return true;
            }

            result = default(T);
            try
            {
                IConvertible convertibleString = (IConvertible)value;
                result = new Nullable<T>((T)convertibleString.ToType(typeof(T), System.Globalization.CultureInfo.CurrentCulture));
            }
            catch(InvalidCastException)
            {
                return false;
            }
            catch (FormatException)
            {
                return false;
            }

           return true;
        }

이것들은 제가 사용했던 기본적인 테스트 케이스들입니다.

        string parseOne = "1";
        int? resultOne;
        bool successOne = parseOne.TryParseStruct<int>(out resultOne);
        Assert.IsTrue(successOne);
        Assert.AreEqual(1, resultOne);

        string parseEmpty = string.Empty;
        int? resultEmpty;
        bool successEmpty = parseEmpty.TryParseStruct<int>(out resultEmpty);
        Assert.IsTrue(successEmpty);
        Assert.IsFalse(resultEmpty.HasValue);

        string parseNull = null;
        int? resultNull;
        bool successNull = parseNull.TryParseStruct<int>(out resultNull);
        Assert.IsTrue(successNull);
        Assert.IsFalse(resultNull.HasValue);

        string parseInvalid = "FooBar";
        int? resultInvalid;
        bool successInvalid = parseInvalid.TryParseStruct<int>(out resultInvalid);
        Assert.IsFalse(successInvalid);

델리게이트를 사용하여 다음 코드는 둘 이상의 구조 유형에 대해 nullable 파싱이 필요하면 재사용을 제공 할 수 있습니다. .Parse () 및 .TryParse () 버전을 모두 여기에 표시했습니다.

다음은 예제 사용법입니다.

NullableParser.TryParseInt(ViewState["Id"] as string);

그리고 여기에 당신을 데려 오는 코드가 있습니다.

public class NullableParser
  {
    public delegate T ParseDelegate<T>(string input) where T : struct;
    public delegate bool TryParseDelegate<T>(string input, out T outtie) where T : struct;
    private static T? Parse<T>(string input, ParseDelegate<T> DelegateTheParse) where T : struct
    {
      if (string.IsNullOrEmpty(input)) return null;
      return DelegateTheParse(input);
    }
    private static T? TryParse<T>(string input, TryParseDelegate<T> DelegateTheTryParse) where T : struct
    {
      T x;
      if (DelegateTheTryParse(input, out x)) return x;
      return null;
    }
    public static int? ParseInt(string input)
    {
      return Parse<int>(input, new ParseDelegate<int>(int.Parse));
    }
    public static int? TryParseInt(string input)
    {
      return TryParse<int>(input, new TryParseDelegate<int>(int.TryParse));
    }
    public static bool? TryParseBool(string input)
    {
      return TryParse<bool>(input, new TryParseDelegate<bool>(bool.TryParse));
    }
    public static DateTime? TryParseDateTime(string input)
    {
      return TryParse<DateTime>(input, new TryParseDelegate<DateTime>(DateTime.TryParse));
    }
  }

이 솔루션은 반사 오버 헤드없이 일반적인 것입니다.

public static Nullable<T> ParseNullable<T>(string s, Func<string, T> parser) where T : struct
{
    if (string.IsNullOrEmpty(s) || string.IsNullOrEmpty(s.Trim())) return null;
    else return parser(s);
}

static void Main(string[] args)
{
    Nullable<int> i = ParseNullable("-1", int.Parse);
    Nullable<float> dt = ParseNullable("3.14", float.Parse);
}

이 시도:

public static int? ParseNullableInt(this string value)
{
    int intValue;
    if (int.TryParse(value, out intValue))
        return intValue;
    return null;
}

이전 주제이지만 방법은 다음과 같습니다.

public static int? ParseToNullableInt(this string value)
{
     return String.IsNullOrEmpty(value) ? null : (int.Parse(value) as int?);
}

TryParse 버전이 ToNullableInt32 (XXX)와 같은 에러를 발생시키지 않도록 requriement null을 구문 분석 할 때 더 좋습니다. 이로 인해 원하지 않는 자동 오류가 발생할 수 있습니다.


조건 연산자와 null 허용 형식 ( TryParse 의 출력에 다시 사용할 수있는 기존 int가없는 경우 두 줄)을 사용할 수 있다는 사실을 사용하면 한 줄에서이 작업을 수행 할 수 있습니다.

Pre C # 7 :

int tempVal;
int? val = Int32.TryParse(stringVal, out tempVal) ? Int32.Parse(stringVal) : (int?)null;

C # 7의 업데이트 된 구문을 사용하면 메서드 호출에서 출력 변수를 선언 할 수 있으므로이 작업은 훨씬 간단 해집니다.

int? val = Int32.TryParse(stringVal, out var tempVal) ? tempVal : (int?)null;

int.TryParse 는 아마도 좀 더 쉽습니다.

public static int? ToNullableInt(this string s)
{
    int i;
    if (int.TryParse(s, out i)) return i;
    return null;
}

@Glenn int.TryParse 편집 하면 "프레임 워크에 내장"됩니다. It 및 int.Parse 는 문자열을 int로 구문 분석 하는 방법입니다.


    public static void Main(string[] args)
    {

        var myString = "abc";

        int? myInt = ParseOnlyInt(myString);
        // null

        myString = "1234";

        myInt = ParseOnlyInt(myString);
        // 1234
    }
    private static int? ParseOnlyInt(string s)
    {
        return int.TryParse(s, out var i) ? i : (int?)null;
    }




nullable