2011-11-17 5 views
58

내가 Get<int>(Stat); 또는암시 적으로 'T'가

Get<string>(Name);하지만 얻을 컴파일 할 때 호출 할 수 있습니다에 유형 '지능'을 변환 할 수 없습니다 :

암시 적으로 'T'

에 유형 'INT'을 변환 할 수 없습니다를

의 경우와 동일합니다.

public T Get<T>(Stats type) where T : IConvertible 
{ 
    if (typeof(T) == typeof(int)) 
    { 
     int t = Convert.ToInt16(PlayerStats[type]); 
     return t; 
    } 
    if (typeof(T) == typeof(string)) 
    { 
     string t = PlayerStats[type].ToString(); 
     return t; 
    } 
} 
+4

블록이 T가 int임을 확인한 것 같습니다. 블록 내에서 T가 int이고 int를 T로 암시 적으로 변환 할 수 있어야합니다.하지만 컴파일러는 해당 추론을 따르지 않으므로, 일반적으로 T는 int에서 파생되지 않으므로 암시 적 변환을 허용하지 않습니다. 컴파일러가 지원한다면 컴파일러는 검증 할 수 없으므로 컴파일 된 어셈블리는 검증 할 수 없습니다. – JGWeissman

답변

99

일반 의 입력을 전환 할 때마다 거의 확실하게 뭔가 잘못된 것을하고 있습니다.. 제네릭은 일반이어야합니다.과 완전히 독립적으로 과 동일하게 작동해야합니다.

T가 int 또는 string 일 수있는 경우 처음부터이 방법으로 코드를 작성하지 마십시오. int를 반환하는 메서드와 문자열을 반환하는 메서드 두 가지를 작성하십시오.

+2

이것이 잘못되었을 때 좀 더 자세히 설명해 주시겠습니까? –

+1

어디서 자동차를 구현하면 IConvertible이 파손될 수 있습니다. 누군가 당신이 일반적인 방법을 가지고있을 때 IConvertible을 구현하는 것을 전달할 수 있다고 가정합니다. – Tjaart

+5

부분적으로 만 동의 할 수 있습니다. @Eric. XML 태그에 저장된 배열을 구문 분석해야하는 상황이 있습니다. 문제는 XML 문서가 따르는 사양입니다 (필자의 경우 COLLADA). float, int 및 bool 일뿐만 아니라 일부 사용자 정의 유형도있을 수 있습니다. 그러나 float [] (배열 태그에는 이름에 저장된 데이터 형식이 포함되어 있습니다 : float_array는 부동 소수점을 저장합니다.) 문자열을 배열로 구문 분석해야합니다. 일부 IFormatProvider가 필요합니다.) 분명히 "T.Parse (...)"를 사용할 수 없습니다. 따라서 작은 하위 집합의 경우 이러한 전환을 사용해야합니다. – rbaleksandar

9
public T Get<T>(Stats type) where T : IConvertible 
{ 
    if (typeof(T) == typeof(int)) 
    { 
     int t = Convert.ToInt16(PlayerStats[type]); 
     return t as T; 
    } 
    if (typeof(T) == typeof(string)) 
    { 
     string t = PlayerStats[type].ToString(); 
     return t as T; 
    } 
} 
+2

null 체크가 필요 없기 때문에'return (T) t; '입니다. – BoltClock

+1

조건 체크가없는 경우 –

+0

하! +1 : 나는 다른 문제가 있었지만 T가 나를 위해 그것을 풀어 준 것처럼 돌아왔다. 고마워. – CodeChops

95

당신은 당신의 사용자 지정 코드 대신 Convert.ChangeType()를 사용할 수 있어야합니다 : 당신이 TypeConverter이 필요한 것처럼, this blog entry를 참조

public T Get<T>(Stats type) where T : IConvertible 
{ 
    return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); 
} 
+2

완벽하게 작동 해 주셔서 감사합니다 –

+7

'return (T) (object) PlayerStats [type]; ' – maxp

+0

해답을 제공해 주셔서 감사합니다. 결코 "절대로"라고 말하지 마십시오. – mikesigs

3

것 같습니다.

6

ChangeType이 가장 좋습니다. 내 솔루션은 BrokenGlass에서 try catch 로직을 사용하여 제공하는 것과 비슷합니다.

static void Main(string[] args) 
{ 
    object number = "1"; 
    bool hasConverted; 
    var convertedValue = DoConvert<int>(number, out hasConverted); 

    Console.WriteLine(hasConverted); 
    Console.WriteLine(convertedValue); 
} 

public static TConvertType DoConvert<TConvertType>(object convertValue, out bool hasConverted) 
{ 
    hasConverted = false; 
    var converted = default(TConvertType); 
    try 
    { 
     converted = (TConvertType) 
      Convert.ChangeType(convertValue, typeof(TConvertType)); 
     hasConverted = true; 
    } 
    catch (InvalidCastException) 
    { 
    } 
    catch (ArgumentNullException) 
    { 
    } 
    catch (FormatException) 
    { 
    } 
    catch (OverflowException) 
    { 
    } 

    return converted; 
} 
4

GUID 형식에 대한 지원하지 않습니다 @BrokenGlass 로직 (Convert.ChangeType)를 고려.

public T Get<T>(Stats type) where T : IConvertible 
{ 
    return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); 
} 

오류 : 'System.Guid'에서 '선택 System.String'에서 잘못된 캐스트.

대신 네임 스페이스를 추가하여 TypeDescriptor.GetConverter을 사용하는 아래 논리를 사용하십시오.

public T Get<T>(Stats type) where T : IConvertible 
{ 
    (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(PlayerStats[type]) 
} 

this을 읽으십시오.

5

이 시도 :

public T Get<T>(Stats type) where T : IConvertible 
{ 
    if (typeof(T) == typeof(int)) 
    { 
     return (T)(object)Convert.ToInt16(PlayerStats[type]); 

    } 
    if (typeof(T) == typeof(string)) 
    { 

     return (T)(object)PlayerStats[type]; 
    } 
} 
+0

도움을 주셔서 감사합니다. 내 필요가 다릅니다. 나는 그것을 테스트 할 수 있도록 기존 정적 메서드에 대한 모의 메서드를 작성하고 있습니다. 이 http://osherove.com/blog/2012/7/8/faking-static-methods-in-moq-fakeiteasy-and-ubstubstitute-migh.html을 사용하십시오. – Esen

0

사실, 당신은 단지 T에 다음 object로 변환 할 수 있습니다. bool에 대한

T var = (T)(object)42;

예 는 :

public class Program 
{ 
    public static T Foo<T>() 
    { 
     if(typeof(T) == typeof(bool)) { 
      return (T)(object)true; 
     } 

     return default(T); 
    } 

    public static void Main() 
    { 
     bool boolValue = Foo<bool>(); // == true 
     string stringValue = Foo<string>(); // == null 
    } 
} 

때때로,이 동작이 바람직하다. 예를 들어 기본 클래스 또는 인터페이스에서 제네릭 메서드를 구현하거나 재정의하는 경우 T 형식을 기반으로 여러 가지 기능을 추가하려고합니다.

관련 문제