[c#] 암시 적으로 ‘Int’형식을 ‘T’로 변환 할 수 없습니다.

전화를 걸 Get<int>(Stat);거나Get<string>(Name);

그러나 컴파일 할 때 다음을 얻습니다.

‘int’유형을 ‘T’로 암시 적으로 변환 할 수 없습니다.

string.

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



답변

제네릭에서 유형을 전환하는 자신을 발견 할 때마다 거의 확실히 뭔가 잘못된 것 입니다. 제네릭해야한다 일반 ; 유형 과는 완전히 독립적으로 동일 하게 작동해야합니다 .

T가 int 또는 string 일 수만 있다면 처음부터 이런 식으로 코드를 작성하지 마십시오. int를 반환하는 메서드와 문자열을 반환하는 메서드를 작성합니다.


답변

Convert.ChangeType()사용자 지정 코드 대신 사용할 수 있어야합니다 .

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


답변

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


답변

ChangeType아마도 최선의 선택 일 것입니다. 내 솔루션은 약간의 try catch 논리를 사용하여 BrokenGlass에서 제공하는 솔루션과 유사합니다.

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


답변

이 시도:

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


답변

사실, 당신은 그것을로 변환 object한 다음 T.

T var = (T)(object)42;

bool:

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유형 에 따라 몇 가지 다른 기능을 추가하려는 경우입니다.


답변

@BrokenGlass 로직 ( Convert.ChangeType)은 GUID 유형을 지원하지 않습니다.

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

오류 : ‘System.String’에서 ‘System.Guid’로의 캐스트가 잘못되었습니다.

대신 네임 스페이스 TypeDescriptor.GetConverter를 추가 하여 아래 로직을 사용하세요 System.ComponentModel.

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

이것을 읽으십시오 .