programing

문자열을 null 가능한 int로 구문 분석하는 방법

megabox 2023. 6. 3. 08:22
반응형

문자열을 null 가능한 int로 구문 분석하는 방법

문자열을 C#.i의 null 가능한 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로 직접 구문 분석할 수 있는 내장 프레임워크 방법이 있는지 알고 싶습니다.

int.TryParse아마 조금 더 쉬울 것입니다.

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

@Glen 편집int.TryParse는 "프레임워크에 내장"됩니다.과 것과그int.Parse문자열을 구문 분석하는 방법입니다.

을 할 수 하여 한로 할 수.nullnull , int출력재수에있음할사용우능경는기줄없존▁of두▁(▁null▁output▁to▁lines▁for가,)▁reuse▁the있음▁a수▁type▁youtwo할용사able(에재▁you▁null▁can력▁if▁int출유우) 출력에 재사용할 수 있습니다.TryParse):

C#7 이전:

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

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

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

[@sblom의 제안에 따라 최신 C#을 사용하도록 업데이트됨]

는 이 를 겪었고 이것으로 . ( 저는이문겪결끝결다니났습이로으것국었국고제를▁(결다▁i니after,if그리고 2returns는 너무 장황합니다!:)

int? ToNullableInt (string val)
    => int.TryParse (val, out var i) ? (int?) i : null;

더 심각한 것은, 혼합하지 않도록 하세요.int#이고, C# 키입니다드워입니다.Int32 Framework 입니다. 지저분하게 입니다.NET Framework BCL. 작동은 하지만 코드가 지저분하게 보일 뿐입니다.

C# >= 7.1

var result = int.TryParse(foo, out var f) ? f : default;

C# 언어 버전을 참조하여 프로젝트에서 지원하는 언어 버전 확인

글렌 슬라벤:nullable int로 직접 구문 분석할 수 있는 내장 프레임워크 방법이 있는지 알고 싶습니다.

값이 null 또는 빈 문자열처럼 유효한 경우 nullable int(int뿐만 아니라)로 직접 구문 분석하지만 잘못된 값에 대한 예외를 발생시키므로 예외를 포착하고 이러한 상황에 대한 기본값을 반환해야 합니다.

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%");

NB: 변환기에 예외를 캡처하는 대신 사용할 수 있는 IsValid 메서드가 있습니다(예외로 인해 예상되는 경우 불필요한 오버헤드가 발생합니다).안타깝게도 .NET 4 이후에만 작동하지만 올바른 DateTime 형식을 확인할 때 로케일을 확인하지 못하는 문제가 있습니다. 버그 93559를 참조하십시오.

오래된 주제지만, 다음은 어떻습니까?

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

나는 이것이 null을 구문 분석하는 요건으로 더 좋습니다. TryParse 버전은 예를 들어 오류를 던지지 않습니다.ToNullableInt32(XXX).원하지 않는 자동 오류가 발생할 수 있습니다.

사용해 보십시오.

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

저는 제 솔루션이 매우 깨끗하고 좋은 솔루션이라고 생각합니다.

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

물론 이것은 제네릭 인수에 정적 방법 "Parse(string)"만 있으면 되는 일반적인 솔루션입니다.이것은 숫자, 부울, 날짜 시간 등에 대해 작동합니다.

다른 모든 대답은 잊어버릴 수 있습니다. 훌륭한 일반적인 솔루션이 있습니다. http://cleansharp.de/wordpress/2011/05/generischer-typeconverter/

이를 통해 다음과 같은 매우 깨끗한 코드를 작성할 수 있습니다.

string value = null;
int? x = value.ConvertOrDefault();

그리고 다음과 같습니다.

object obj = 1;  

string value = null;
int x = 5;
if (value.TryConvert(out x))
    Console.WriteLine("TryConvert example: " + x); 

bool boolean = "false".ConvertOrDefault();
bool? nullableBoolean = "".ConvertOrDefault();
int integer = obj.ConvertOrDefault();
int negativeInteger = "-12123".ConvertOrDefault();
int? nullableInteger = value.ConvertOrDefault();
MyEnum enumValue = "SecondValue".ConvertOrDefault();

MyObjectBase myObject = new MyObjectClassA();
MyObjectClassA myObjectClassA = myObject.ConvertOrDefault();

구문 분석이 불가능한 경우 기본값을 정의할 수 있는 기능으로 문자열을 int 값으로 구문 분석하기 위한 다음 확장 방법을 제안합니다.

public static int ParseInt(this string value, int defaultIntValue = 0)
        {
            return int.TryParse(value, out var parsedInt) ? parsedInt : defaultIntValue;
        }

public static int? ParseNullableInt(this string value)
        {
            if (string.IsNullOrEmpty(value))
                return null;

            return value.ParseInt();
        }

다음은 모든 구조 유형에 대해 작동해야 합니다.MSDN 포럼의 Matt Manela 코드를 기반으로 합니다.Murph가 지적했듯이 예외 처리는 Type 전용 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 int로 직접 구문 분석할 수 있는 내장 프레임워크 방법이 있는지 알고 싶습니다.

없습니다.

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

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

좀 더 일반적인 내 것을 공유해야겠다고 느꼈습니다.

용도:

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

첫 번째 버전은 트라이캐치가 필요해서 더 느리지만 더 깨끗해 보입니다.유효하지 않은 문자열로 여러 번 호출되지 않을 경우에는 그다지 중요하지 않습니다.성능이 문제인 경우 TryParse 메서드를 사용할 때 컴파일러에서 유추할 수 없으므로 ParseBy의 형식 매개 변수를 지정해야 합니다.또한 Func<>에서 out 키워드를 사용할 수 없도록 대리자를 정의해야 했지만, 적어도 이번에는 컴파일러가 명시적인 인스턴스를 필요로 하지 않습니다.

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

Generic NullableParser 클래스의 일부 코드를 찾아 수정했습니다.전체 코드는 내 블로그 Nullable TryParse에 있습니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
namespace SomeNamespace
{
    /// <summary>
    /// A parser for nullable types. Will return null when parsing fails.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    ///
    public static class NullableParser<T> where T : struct
    {
        public delegate bool TryParseDelegate(string s, out T result);
        /// <summary>
        /// A generic Nullable Parser. Supports parsing of all types that implements the tryParse method;
        /// </summary>
        /// <param name="text">Text to be parsed</param>
        /// <param name="result">Value is true for parse succeeded</param>
        /// <returns>bool</returns>
        public static bool TryParse(string s, out Nullable<T> result)
        {
            bool success = false;
            try
            {
                if (string.IsNullOrEmpty(s))
                {
                    result = null;
                    success = true;
                }
                else
                {
                    IConvertible convertableString = s as IConvertible;
                    if (convertableString != null)
                    {
                        result = new Nullable<T>((T)convertableString.ToType(typeof(T),
                            CultureInfo.CurrentCulture));
                        success = true;
                    }
                    else
                    {
                        success = false;
                        result = null;
                    }
                }
            }
            catch
            {
                success = false;
                result = null;
            }
            return success;
        }
    }
}
    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;
    }

더 깨끗한 방법은 별도의 함수 또는 확장 방법을 작성하는 것이지만, 한 줄로 된 선만 작성하는 경우:

string s;
int? i = s == null ? (int?)null : int.Parse(s);

굳이 예외를 사용하지 않아도 된다면 절대로 예외를 사용해서는 안 됩니다. 간접비는 끔찍합니다.

TryParse의 변형은 문제를 해결합니다. 만약 당신이 창의적으로 (코드를 더 우아하게 보이게 하기 위해) 당신은 아마도 3.5의 확장 방법으로 무언가를 할 수 있지만 코드는 거의 같을 것입니다.

두 개 이상의 구조 유형에 대해 nullable 구문 분석이 필요한 경우 대리인을 사용하여 다음 코드를 재사용할 수 있습니다.두 가지 다 보여드렸습니다.구문 분석() 및 .여기에서 Parse() 버전을 사용해 보십시오.

다음은 사용 예입니다.

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

저는 이것이 오래된 주제라는 것을 알고 있지만, 간단히 말씀해 주시겠습니까?

(Nullable<int>)int.Parse(stringVal);

?

저는 제 요구 사항을 충족하는 이것을 생각해냈습니다(저는 제 확장 메서드가 프레임워크의 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;
}

아래 코드를 제안합니다.변환 오류가 발생한 경우 예외적으로 작업할 수 있습니다.

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

코드에서 이 확장 메서드를 사용합니다(입력하시겠습니까?사용자 클래스의 연령 속성):

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

OR

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

언급URL : https://stackoverflow.com/questions/45030/how-to-parse-a-string-into-a-nullable-int

반응형