Я могу позвонить 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, а другой - строку.
источник
int, int?, bool, bool?, string
, и это казалось невозможным.Вы должны иметь возможность просто использовать
Convert.ChangeType()
вместо своего собственного кода:public T Get<T>(Stats type) where T : IConvertible { return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); }
источник
return (T)(object)PlayerStats[type];
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; } }
источник
return (T) t;
потому что никаких нулевых проверок не требуется.ChangeType
вероятно, ваш лучший вариант. Мое решение похоже на то, которое предоставляет 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]) }
Прочтите это .
источник
Похоже, вам нужен
TypeConverter
, см. Эту запись в блоге .источник
Вы можете просто использовать, как показано ниже,
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; } }
источник