[C#] 문자열을 널 입력 가능 유형으로 변환 (int, double 등)

데이터 변환을 시도하고 있습니다. 불행히도, 대부분의 데이터는 int 또는 double이어야하는 문자열에 있습니다 …

내가 가진 것은 다음과 같습니다.

double? amount = Convert.ToDouble(strAmount);

이 접근 방식의 문제점은 strAmount가 비어 있으면 비어 있으면 null이되기를 원하므로 데이터베이스에 추가하면 열이 null입니다. 그래서 나는 이것을 작성했다 :

double? amount = null;
if(strAmount.Trim().Length>0)
{
    amount = Convert.ToDouble(strAmount);
}

이제는 잘 작동하지만 이제는 한 줄 대신 다섯 줄의 코드가 있습니다. 이것은 특히 변환 할 열이 많을 때 일을 읽기가 더 어려워집니다.

나는 문자열 클래스에 대한 확장을 사용하고 타입을 전달하기 위해 generic을 확장한다고 생각했다. 이것은 double, int 또는 long 일 수 있기 때문이다. 그래서 나는 이것을 시도했다 :

public static class GenericExtension
{
    public static Nullable<T> ConvertToNullable<T>(this string s, T type) where T: struct
    {
        if (s.Trim().Length > 0)
        {
            return (Nullable<T>)s;
        }
        return null;
    }
}

그러나 오류가 발생합니다 : ‘string’유형을 ‘T’로 변환 할 수 없습니까?

이 주위에 방법이 있습니까? 제네릭을 사용하여 메서드를 만드는 데 익숙하지 않습니다.



답변

명심해야 할 또 다른 사항은 문자열 자체가 null 일 수 있다는 것입니다.

public static Nullable<T> ToNullable<T>(this string s) where T: struct
{
    Nullable<T> result = new Nullable<T>();
    try
    {
        if (!string.IsNullOrEmpty(s) && s.Trim().Length > 0)
        {
            TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
            result = (T)conv.ConvertFrom(s);
        }
    }
    catch { } 
    return result;
}


답변

아래 확장 방법을 사용해보십시오.

public static T? GetValueOrNull<T>(this string valueAsString)
    where T : struct 
{
    if (string.IsNullOrEmpty(valueAsString))
        return null;
    return (T) Convert.ChangeType(valueAsString, typeof(T));
}

이 방법으로 할 수 있습니다 :

double? amount = strAmount.GetValueOrNull<double>();
int? amount = strAmount.GetValueOrNull<int>();
decimal? amount = strAmount.GetValueOrNull<decimal>();


답변

이건 어때?


double? amount = string.IsNullOrEmpty(strAmount) ? (double?)null : Convert.ToDouble(strAmount);

물론 이것은 변환 실패를 고려하지 않습니다.


답변

이 제네릭 형식 변환기를 작성했습니다. Nullable 및 표준 값과 함께 작동하며 문자열뿐만 아니라 모든 컨버터블 유형 간을 변환합니다. 예상되는 모든 종류의 시나리오 (기본값, null 값, 기타 값 등)를 처리합니다.

나는 이것을 수십 개의 프로덕션 프로그램에서 약 1 년 동안 사용해 왔으므로 꽤 견고해야합니다.

    public static T To<T>(this IConvertible obj)
    {
        Type t = typeof(T);

        if (t.IsGenericType
            && (t.GetGenericTypeDefinition() == typeof(Nullable<>)))
        {
            if (obj == null)
            {
                return (T)(object)null;
            }
            else
            {
                return (T)Convert.ChangeType(obj, Nullable.GetUnderlyingType(t));
            }
        }
        else
        {
            return (T)Convert.ChangeType(obj, t);
        }
    }

    public static T ToOrDefault<T>
                 (this IConvertible obj)
    {
        try
        {
            return To<T>(obj);
        }
        catch
        {
            return default(T);
        }
    }

    public static bool ToOrDefault<T>
                        (this IConvertible obj,
                         out T newObj)
    {
        try
        {
            newObj = To<T>(obj);
            return true;
        }
        catch
        {
            newObj = default(T);
            return false;
        }
    }

    public static T ToOrOther<T>
                           (this IConvertible obj,
                           T other)
    {
        try
        {
            return To<T>(obj);
        }
        catch
        {
            return other;
        }
    }

    public static bool ToOrOther<T>
                             (this IConvertible obj,
                             out T newObj,
                             T other)
    {
        try
        {
            newObj = To<T>(obj);
            return true;
        }
        catch
        {
            newObj = other;
            return false;
        }
    }

    public static T ToOrNull<T>
                          (this IConvertible obj)
                          where T : class
    {
        try
        {
            return To<T>(obj);
        }
        catch
        {
            return null;
        }
    }

    public static bool ToOrNull<T>
                      (this IConvertible obj,
                      out T newObj)
                      where T : class
    {
        try
        {
            newObj = To<T>(obj);
            return true;
        }
        catch
        {
            newObj = null;
            return false;
        }
    }


답변

시도해 볼 수 있습니다.

TypeConverter conv = TypeDescriptor.GetConverter(typeof(int));
conv.ConvertFrom(mystring);

자신의 null 검사를 수행하고 int?필요한 경우 반환 하십시오. 당신은 또한 그것을try {}


답변

이 기회를 …

public delegate bool TryParseDelegate<T>(string data, out T output);

public static T? ToNullablePrimitive<T>(this string data, 
    TryParseDelegate<T> func) where T:struct
{
    string.IsNullOrEmpty(data) return null;

    T output;

    if (func(data, out output))
    {
        return (T?)output;
    }

    return null;
}

그럼 이렇게 불러

void doStuff()
{
    string foo = "1.0";

    double? myDouble = foo.ToNullablePrimitive<double>(double.TryParse);

    foo = "1";

    int? myInt = foo.ToNullablePrimitive<int>(int.TryParse);

    foo = "haha";

    int? myInt2 = foo.ToNullablePrimitive<int>(int.TryParse);
}


답변

나는 Joel의 대답을 좋아하지만 예외를 먹는 팬이 아니기 때문에 약간 수정했습니다.

    /// <summary>
    /// Converts a string to the specified nullable type.
    /// </summary>
    /// <typeparam name="T">The type to convert to</typeparam>
    /// <param name="s">The string to convert</param>
    /// <returns>The nullable output</returns>
    public static T? ToNullable<T>(this string s) where T : struct
    {
        if (string.IsNullOrWhiteSpace(s))
            return null;

        TypeConverter conv = TypeDescriptor.GetConverter(typeof (T));
        return (T) conv.ConvertFrom(s);
    }

    /// <summary>
    /// Attempts to convert a string to the specified nullable primative.
    /// </summary>
    /// <typeparam name="T">The primitive type to convert to</typeparam>
    /// <param name="data">The string to convert</param>
    /// <param name="output">The nullable output</param>
    /// <returns>
    /// True if conversion is successfull, false otherwise.  Null and whitespace will
    /// be converted to null and return true.
    /// </returns>
    public static bool TryParseNullable<T>(this string data, out T? output) where T : struct
    {
        try
        {
            output = data.ToNullable<T>();
            return true;
        }
        catch
        {
            output = null;
            return false;
        }
    }