Eu posso ligar Get<int>(Stat);
ouGet<string>(Name);
Mas, ao compilar, recebo:
Não é possível converter implicitamente o tipo 'int' em 'T'
e a mesma coisa 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;
}
}
Respostas:
Sempre que você liga um tipo em um genérico, é quase certo que está fazendo algo errado . Os genéricos devem ser genéricos ; eles devem operar de forma idêntica e completamente independente do tipo .
Se T só puder ser int ou string, não escreva seu código dessa maneira em primeiro lugar. Escreva dois métodos, um que retorna um int e outro que retorna uma string.
fonte
int, int?, bool, bool?, string
, e parecia impossível.Você deve ser capaz de usar apenas em
Convert.ChangeType()
vez de seu código personalizado:public T Get<T>(Stats type) where T : IConvertible { return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); }
fonte
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; } }
fonte
return (T) t;
porque nenhuma verificação nula é necessária.ChangeType
é provavelmente a sua melhor opção. Minha solução é semelhante à fornecida por BrokenGlass com um pouco de lógica 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; }
fonte
Experimente isto:
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]; } }
fonte
Na verdade, você pode simplesmente convertê-lo para
object
e depois paraT
.T var = (T)(object)42;
Um exemplo 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 } }
Às vezes, esse comportamento é desejável. Por exemplo, ao implementar ou sobrescrever um método genérico de uma classe ou interface base e você deseja adicionar algumas funcionalidades diferentes com base no
T
tipo.fonte
Considerando que a lógica @BrokenGlass (
Convert.ChangeType
) não oferece suporte para o tipo de GUID.public T Get<T>(Stats type) where T : IConvertible { return (T) Convert.ChangeType(PlayerStats[type], typeof(T)); }
Erro : conversão inválida de 'System.String' para 'System.Guid'.
Em vez disso, use a lógica abaixo
TypeDescriptor.GetConverter
adicionandoSystem.ComponentModel
namespace.public T Get<T>(Stats type) where T : IConvertible { (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(PlayerStats[type]) }
Leia isso .
fonte
Parece que você precisa de um
TypeConverter
, consulte esta entrada do blog .fonte
Você pode simplesmente lançar como abaixo,
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; } }
fonte