Puedo llamar Get<int>(Stat);
oGet<string>(Name);
Pero al compilar obtengo:
No se puede convertir implícitamente el tipo 'int' a 'T'
y lo mismo para 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;
}
}
Respuestas:
Cada vez que se encuentra encendiendo un tipo en un genérico , es casi seguro que está haciendo algo mal . Los genéricos deben ser genéricos ; deben operar de manera idéntica completamente independiente del tipo .
Si T solo puede ser int o string, entonces no escriba su código de esta manera en primer lugar. Escriba dos métodos, uno que devuelva un int y otro que devuelva una cadena.
fuente
int, int?, bool, bool?, string
, y aparentemente era imposible.Debería poder usar en
Convert.ChangeType()
lugar de su código personalizado:public T Get<T>(Stats type) where T : IConvertible { return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); }
fuente
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; } }
fuente
return (T) t;
porque no son necesarias comprobaciones nulas.ChangeType
es probablemente tu mejor opción. Mi solución es similar a la proporcionada por BrokenGlass con un poco de lógica de captura de prueba.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; }
fuente
Prueba esto:
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]; } }
fuente
En realidad, puede convertirlo a
object
y luego aT
.T var = (T)(object)42;
Un ejemplo para
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 } }
A veces, este comportamiento es deseable. Por ejemplo, al implementar o anular un método genérico de una clase base o interfaz y desea agregar algunas funcionalidades diferentes según el
T
tipo.fuente
Teniendo en cuenta que @BrokenGlass, la lógica (
Convert.ChangeType
) no es compatible con el tipo GUID.public T Get<T>(Stats type) where T : IConvertible { return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); }
Error : conversión no válida de 'System.String' a 'System.Guid'.
En su lugar, use la siguiente lógica usando
TypeDescriptor.GetConverter
agregandoSystem.ComponentModel
espacio de nombres.public T Get<T>(Stats type) where T : IConvertible { (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(PlayerStats[type]) }
Lea esto .
fuente
Parece que necesita un
TypeConverter
, consulte esta entrada de blog .fuente
Simplemente puede lanzar como a continuación,
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; } }
fuente