Не удается неявно преобразовать тип ' 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;
    }
}
8 62

8 ответов:

каждый раз, когда вы обнаружите, что включаете тип в общем вы почти наверняка делаете что-то неправильно. Дженерики должны быть generic; они должны работать одинаково полностью не зависит от типа.

Если 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 скорее всего ваш лучший вариант. Мое решение похоже на то, которое предоставляет 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;
}

попробуйте это:

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

учитывая логику @ BrokenGlass (Convert.ChangeType) не поддерживает тип GUID.

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

: недопустимое приведение из ' системы.Строка' до 'системы.Guid'.

вместо этого используйте логику ниже, используя TypeDescriptor.GetConverter добавлять System.ComponentModel пространство имен.

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

читать этой.

похоже, вам нужен TypeConverter см. запись в блоге.

на самом деле, вы можете просто преобразовать его в 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 тип.