Mogę zadzwonić Get<int>(Stat);
lubGet<string>(Name);
Ale podczas kompilacji otrzymuję:
Nie można niejawnie przekonwertować typu „int” na „T”
i to samo dla 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;
}
}
Odpowiedzi:
Za każdym razem, gdy włączasz typ w rodzaju ogólnym , prawie na pewno robisz coś złego . Generyczne powinny być generyczne ; powinny działać identycznie, całkowicie niezależnie od typu .
Jeśli T może mieć tylko wartość int lub string, nie pisz swojego kodu w ten sposób w ogóle. Napisz dwie metody, jedną zwracającą int, a drugą zwracającą ciąg.
źródło
int, int?, bool, bool?, string
i wydawało się, że jest to niemożliwe.Powinieneś móc po prostu użyć
Convert.ChangeType()
zamiast niestandardowego kodu:public T Get<T>(Stats type) where T : IConvertible { return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); }
źródło
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; } }
źródło
return (T) t;
ponieważ nie są konieczne żadne sprawdzenia zerowe.ChangeType
to prawdopodobnie najlepsza opcja. Moje rozwiązanie jest podobne do tego dostarczonego przez BrokenGlass z odrobiną logiki 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; }
źródło
Spróbuj tego:
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]; } }
źródło
Właściwie możesz po prostu przekonwertować go na,
object
a następnie naT
.T var = (T)(object)42;
Przykład dla
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 } }
Czasami takie zachowanie jest pożądane. Na przykład podczas implementowania lub zastępowania metody ogólnej z klasy bazowej lub interfejsu i chcesz dodać różne funkcje w zależności od
T
typu.źródło
Biorąc pod uwagę, że logika @BrokenGlass (
Convert.ChangeType
) nie obsługuje typu GUID.public T Get<T>(Stats type) where T : IConvertible { return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); }
Błąd : nieprawidłowe przesyłanie z „System.String” na „System.Guid”.
Zamiast tego użyj poniższej logiki
TypeDescriptor.GetConverter
, dodającSystem.ComponentModel
przestrzeń nazw.public T Get<T>(Stats type) where T : IConvertible { (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(PlayerStats[type]) }
Przeczytaj to .
źródło
Wygląda na to, że potrzebujesz
TypeConverter
, zobacz ten wpis na blogu .źródło
Możesz po prostu rzucić jak poniżej,
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; } }
źródło