메소드의 리턴 유형을 일반으로 만들려면 어떻게합니까?


166

이 메소드를 일반화하여 문자열, bool, int 또는 double을 리턴 할 수있는 방법이 있습니까? 지금은 문자열을 반환하지만 구성 값으로 "true"또는 "false"를 찾을 수 있으면 예를 들어 bool을 반환하고 싶습니다.

    public static string ConfigSetting(string settingName)
    {  
         return ConfigurationManager.AppSettings[settingName];
    }

각 설정이 어떤 유형인지 알 수있는 방법이 있습니까?
thecoshman

2
정말로 물어보고 싶은 질문은 "응용 프로그램 구성을 어떻게 강력하게 구성합니까?"입니다. 그래도 적절한 답변을 작성하기 위해 함께 일한 지 너무 오래되었습니다.
Simon

예, 이상적으로 유형을 메소드에 전달하고 싶지 않습니다. 내가 언급 한 4 가지 유형 만 가질 것입니다. 따라서 "true"/ "false"가 설정되어 있으면이 함수가 부울을 반환하고 (메소드에 전달할 필요없이) int와 double을 double로 결합 할 수 있으며 다른 모든 것은 문자열이어야합니다. 이미 답변 된 것은 잘 작동하지만 매번 유형을 전달해야합니다. 아마 괜찮을 것입니다.
MacGyver

3
귀하의 의견 은 런타임 에 설정 이름 키에 대해 검색 된 실제 데이터를 기반으로 강력한 형식의 부울 (또는 문자열 또는 int 또는 가지고있는 것) 반환하는 메소드를 요청하는 것처럼 들립니다 . C #은 그렇게하지 않습니다. 컴파일 타임에 해당 값의 유형을 알 수있는 방법이 없습니다. 즉, 정적 입력이 아니라 동적 입력입니다. dynamic키워드 를 사용하면 C #에서이를 수행 할 수 있습니다 . 그에 대한 성능 비용이 있지만 구성 파일을 읽으면 성능 비용이 거의 중요하지 않습니다.
Poogog

답변:


354

다음과 같은 일반적인 방법으로 만들어야합니다.

public static T ConfigSetting<T>(string settingName)
{  
    return /* code to convert the setting to T... */
}

그러나 호출자 는 예상되는 유형을 지정해야합니다. 그런 다음 Convert.ChangeType모든 관련 유형이 지원된다고 가정하여을 사용할 수 있습니다 .

public static T ConfigSetting<T>(string settingName)
{  
    object value = ConfigurationManager.AppSettings[settingName];
    return (T) Convert.ChangeType(value, typeof(T));
}

나는이 모든 것이 좋은 생각이라고 전적으로 확신하지는 않습니다.


21
/ * 코드를 설정을 T로 변환하는 코드 ... * / 여기 전체 소설을 따릅니다 :)
Adrian Iftode

1
이것은 당신이 얻고 자하는 설정의 유형을 알 필요가 없을 것입니다.
thecoshman

2
@ thecoshman : 그렇다면, 그렇지 않으면 반환 된 값으로 무엇을합니까?
George Duckett

5
이 대답은 물론 정확하다, 당신이 만족에게 OP의 요청을주의, 그것은 별도의 방법 (옛 접근하는 것이 아마 언급 할만큼 가치이지만 ConfigSettingString, ConfigSettingBool,, 등)이 짧아집니다 방법 기관의 장점이 명확하게, 그리고 더 나은 집중 .
Poogog

4
이것이 권장되지 않는 경우 일반 리턴 유형의 목적은 무엇입니까?
bobbyalex

29

당신은 사용할 수 있습니다 Convert.ChangeType():

public static T ConfigSetting<T>(string settingName)
{
    return (T)Convert.ChangeType(ConfigurationManager.AppSettings[settingName], typeof(T));
}

13

이를 수행하는 방법에는 여러 가지가 있습니다 (우선 순위에 따라 OP의 문제에 따라 나열 됨)

  1. 옵션 1 : 직선 접근 -하나의 일반 함수를 사용하지 않고 예상되는 각 유형에 대해 여러 함수를 작성하십시오.

    public static bool ConfigSettingInt(string settingName)
    {  
         return Convert.ToBoolean(ConfigurationManager.AppSettings[settingName]);
    }
    
  2. 옵션 2 : 멋진 변환 방법을 사용하지 않으려는 경우 -값을 객체로 캐스트 한 다음 일반 유형으로 캐스트하십시오.

    public static T ConfigSetting<T>(string settingName)
    {  
         return (T)(object)ConfigurationManager.AppSettings[settingName];
    }
    

    참고- 캐스트가 유효하지 않은 경우 오류가 발생합니다 (귀하의 경우). 유형 캐스팅에 대해 잘 모르면 옵션 3으로 이동하십시오.

  3. 옵션 3 : 형식 안전성이 있는 일반-형식 변환을 처리하는 일반 함수를 만듭니다.

    public static T ConvertValue<T,U>(U value) where U : IConvertible
    {
        return (T)Convert.ChangeType(value, typeof(T));
    } 
    

    참고 -T는 예상되는 유형입니다. 여기서 where 제약 조건을 참고하십시오 (U의 유형은 I에서 변환 가능해야 오류에서 벗어날 수 있습니다)


4
왜 세 번째 옵션을 일반화 U합니까? 그렇게 할 필요는 없으며 메서드를 호출하기가 더 어렵습니다. IConvertible대신 수락하십시오 . 나는이 질문에 대한 두 번째 옵션을 포함시키는 것이 가치가 있다고 생각하지 않습니다. 첫 번째 옵션에서 메소드의 이름을
Jon Skeet

7

메소드의 리턴 값 유형을 호출하는 동안 메소드에 전달하는 일반 유형으로 변환해야합니다.

    public static T values<T>()
    {
        Random random = new Random();
        int number = random.Next(1, 4);
        return (T)Convert.ChangeType(number, typeof(T));
    }

해당 메서드를 통해 반환되는 값에 대해 형식을 지정할 수있는 형식을 전달해야합니다.

전달할 수있는 제네릭 형식으로 형식을 지정할 수없는 값을 반환하려면 코드를 변경하거나 메서드의 반환 값으로 형식을 지정할 수있는 형식을 전달해야합니다. 따라서이 방법은 권장되지 않습니다.


스팟에 - 나를 위해 마지막 줄에 return (T)Convert.ChangeType(number, typeof(T));환호 - 정확히 내가 실종이었다
그렉 Trevellick을

1

함수를 작성하고 일반 매개 변수로 put 매개 변수를 전달하십시오.

 public static T some_function<T>(T out_put_object /*declare as Output object*/)
    {
        return out_put_object;
    }

이것은 실제로 몇 가지 유스 케이스에 매우 똑똑합니다. 데이터베이스에서 데이터를 가져 오는 것과 같습니다. T 타입의 데이터 목록을 얻을 수 있다는 것을 알고 있습니다. 로딩 방법은 현재 어떤 T 타입을 원하는지 모릅니다. 따라서 새로운 List <WantedObject>를 이것에 전달하면 메소드가 작업을 수행하고 목록을 반환하기 전에 채울 수 있습니다. 좋은!
Marco Heumann

0

아래 코드를 시도하십시오 :

public T? GetParsedOrDefaultValue<T>(string valueToParse) where T : struct, IComparable
{
 if(string.EmptyOrNull(valueToParse))return null;
  try
  {
     // return parsed value
     return (T) Convert.ChangeType(valueToParse, typeof(T));
  }
  catch(Exception)
  {
   //default as null value
   return null;
  }
 return null;
}

-1
 private static T[] prepareArray<T>(T[] arrayToCopy, T value)
    {
        Array.Copy(arrayToCopy, 1, arrayToCopy, 0, arrayToCopy.Length - 1);
        arrayToCopy[arrayToCopy.Length - 1] = value;
        return (T[])arrayToCopy;
    }

내 코드 전체 에서이 작업을 수행하고 메소드에 넣는 방법을 원했습니다. 내 반환 값에 Convert.ChangeType을 사용할 필요가 없으므로 여기에서 공유하고 싶었습니다. 이것은 모범 사례는 아니지만 나를 위해 일했습니다. 이 메소드는 제네릭 형식의 배열과 배열 끝에 추가 할 값을받습니다. 그런 다음 첫 번째 값을 제거하고 배열을 복사하고 메소드에 취한 값을 배열의 끝에 추가합니다. 마지막으로 일반 배열을 반환합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.