[c#] C #에서 제네릭 메서드 만들기

비슷한 방법을 여러 가지 일반적인 방법으로 결합하려고합니다. 쿼리 문자열의 값을 반환하는 여러 메서드가 있습니다. 해당 쿼리 문자열이 없거나 올바른 형식이 아닌 경우 null입니다. 모든 유형이 기본적으로 nullable이면 충분하지만 정수 및 날짜에는 nullable 제네릭 유형을 사용해야합니다.

여기 내가 지금 가지고있는 것입니다. 그러나 숫자 값이 유효하지 않고 불행히도 내 시나리오에서 유효한 값인 경우 0을 다시 전달합니다. 누군가 나를 도울 수 있습니까? 감사!

public static T GetQueryString<T>(string key) where T : IConvertible
{
    T result = default(T);

    if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
    {
        string value = HttpContext.Current.Request.QueryString[key];

        try
        {
            result = (T)Convert.ChangeType(value, typeof(T));
        }
        catch
        {
            //Could not convert.  Pass back default value...
            result = default(T);
        }
    }

    return result;
}



답변

default (T)를 사용하는 대신 반환 할 기본값을 지정한 경우 어떻게됩니까?

public static T GetQueryString<T>(string key, T defaultValue) {...}

전화를 더 쉽게 할 수 있습니다.

var intValue = GetQueryString("intParm", Int32.MinValue);
var strValue = GetQueryString("strParm", "");
var dtmValue = GetQueryString("dtmPatm", DateTime.Now); // eg use today's date if not specified

단점은 유효하지 않거나 누락 된 쿼리 문자열 값을 나타 내기 위해 매직 값이 필요하다는 것입니다.


답변

알아, 알아,하지만 …

public static bool TryGetQueryString<T>(string key, out T queryString)


답변

이건 어때? 반환 유형을에서 T로 변경Nullable<T>

public static Nullable<T> GetQueryString<T>(string key) where T : struct, IConvertible
        {
            T result = default(T);

            if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
            {
                string value = HttpContext.Current.Request.QueryString[key];

                try
                {
                    result = (T)Convert.ChangeType(value, typeof(T));
                }
                catch
                {
                    //Could not convert.  Pass back default value...
                    result = default(T);
                }
            }

            return result;
        }


답변

어쩌면 어쩌면 모나드를 사용할 수 있습니다 (제이의 대답을 선호하지만)

public class Maybe<T>
{
    private readonly T _value;

    public Maybe(T value)
    {
        _value = value;
        IsNothing = false;
    }

    public Maybe()
    {
        IsNothing = true;
    }

    public bool IsNothing { get; private set; }

    public T Value
    {
        get
        {
            if (IsNothing)
            {
                throw new InvalidOperationException("Value doesn't exist");
            }
            return _value;
        }
    }

    public override bool Equals(object other)
    {
        if (IsNothing)
        {
            return (other == null);
        }
        if (other == null)
        {
            return false;
        }
        return _value.Equals(other);
    }

    public override int GetHashCode()
    {
        if (IsNothing)
        {
            return 0;
        }
        return _value.GetHashCode();
    }

    public override string ToString()
    {
        if (IsNothing)
        {
            return "";
        }
        return _value.ToString();
    }

    public static implicit operator Maybe<T>(T value)
    {
        return new Maybe<T>(value);
    }

    public static explicit operator T(Maybe<T> value)
    {
        return value.Value;
    }
}

방법은 다음과 같습니다.

    public static Maybe<T> GetQueryString<T>(string key) where T : IConvertible
    {
        if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
        {
            string value = HttpContext.Current.Request.QueryString[key];

            try
            {
                return (T)Convert.ChangeType(value, typeof(T));
            }
            catch
            {
                //Could not convert.  Pass back default value...
                return new Maybe<T>();
            }
        }

        return new Maybe<T>();
    }


답변

Convert.ChangeType().NET 2.0 BCL에서 nullable 형식 또는 열거 형을 올바르게 처리하지 않습니다 (하지만 BCL 4.0에서는 수정되었다고 생각합니다). 외부 구현을 더 복잡하게 만들기보다는 변환기가 더 많은 작업을 수행하도록 만드십시오. 내가 사용하는 구현은 다음과 같습니다.

public static class Converter
{
  public static T ConvertTo<T>(object value)
  {
    return ConvertTo(value, default(T));
  }

  public static T ConvertTo<T>(object value, T defaultValue)
  {
    if (value == DBNull.Value)
    {
      return defaultValue;
    }
    return (T) ChangeType(value, typeof(T));
  }

  public static object ChangeType(object value, Type conversionType)
  {
    if (conversionType == null)
    {
      throw new ArgumentNullException("conversionType");
    }

    // if it's not a nullable type, just pass through the parameters to Convert.ChangeType
    if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
    {
      // null input returns null output regardless of base type
      if (value == null)
      {
        return null;
      }

      // it's a nullable type, and not null, which means it can be converted to its underlying type,
      // so overwrite the passed-in conversion type with this underlying type
      conversionType = Nullable.GetUnderlyingType(conversionType);
    }
    else if (conversionType.IsEnum)
    {
      // strings require Parse method
      if (value is string)
      {
        return Enum.Parse(conversionType, (string) value);
      }
      // primitive types can be instantiated using ToObject
      else if (value is int || value is uint || value is short || value is ushort ||
           value is byte || value is sbyte || value is long || value is ulong)
      {
        return Enum.ToObject(conversionType, value);
      }
      else
      {
        throw new ArgumentException(String.Format("Value cannot be converted to {0} - current type is " +
                              "not supported for enum conversions.", conversionType.FullName));
      }
    }

    return Convert.ChangeType(value, conversionType);
  }
}

그러면 GetQueryString <T> 구현은 다음과 같습니다.

public static T GetQueryString<T>(string key)
{
    T result = default(T);
    string value = HttpContext.Current.Request.QueryString[key];

    if (!String.IsNullOrEmpty(value))
    {
        try
        {
            result = Converter.ConvertTo<T>(value);
        }
        catch
        {
            //Could not convert.  Pass back default value...
            result = default(T);
        }
    }

    return result;
}


답변

이 클래스 설정 {public int X {get; set;} public string Y {get; 세트; } // 필요에 따라 반복

 public settings()
 {
    this.X = defaultForX;
    this.Y = defaultForY;
    // repeat ...
 }
 public void Parse(Uri uri)
 {
    // parse values from query string.
    // if you need to distinguish from default vs. specified, add an appropriate property

 }

이것은 100 개의 프로젝트에서 잘 작동했습니다. 다른 많은 구문 분석 솔루션 중 하나를 사용하여 값을 구문 분석 할 수 있습니다.


답변