Quiero convertir una cadena a un tipo genérico como int
o date
, o long
sobre la base del tipo de retorno genérico.
Básicamente, una función como Parse<T>(String)
esa devuelve un elemento de tipo T
.
Por ejemplo, si se pasó un int, la función debería hacerlo int.parse
internamente.
c#
string
parsing
type-conversion
Karim
fuente
fuente
IConvertable
¿no debería restringir también elT
, es decirT ChangeType<T>(this object obj) where T : IConvertable
?obj
debe ser asíIConvertible
, pero no hay forma de especificarlo en tiempo de compilación.Bueno, parece que llegué demasiado tarde para responder en este hilo. Pero aquí está mi implementación:
Básicamente, he creado un método de extensión para la clase Object. Maneja todos los tipos, es decir, que aceptan valores NULL, clases y estructuras.
public static T ConvertTo<T>(this object value) { T returnValue; if (value is T variable) returnValue = variable; else try { //Handling Nullable types i.e, int?, double?, bool? .. etc if (Nullable.GetUnderlyingType(typeof(T)) != null) { TypeConverter conv = TypeDescriptor.GetConverter(typeof(T)); returnValue = (T) conv.ConvertFrom(value); } else { returnValue = (T) Convert.ChangeType(value, typeof(T)); } } catch (Exception) { returnValue = default(T); } return returnValue; }
fuente
TypeDescriptor
para tipos que aceptan valores NULL yConvert.ChangeType
para los que no aceptan valores NULL? Todo estetry
bloque se puede reducir solo aTypeConverter
2 líneas de código y funcionará tanto para nulos como para no nulos.System.Convert.ChangeType
no se convierte a ningún tipo. Piense en lo siguiente:Estas conversiones son posibles con esta implementación de ChangeType .
fuente
versión más limpia de la respuesta de Pranay
public static T ConvertTo<T>(this object value) { if (value is T variable) return variable; try { //Handling Nullable types i.e, int?, double?, bool? .. etc if (Nullable.GetUnderlyingType(typeof(T)) != null) { return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value); } return (T)Convert.ChangeType(value, typeof(T)); } catch (Exception) { return default(T); } }
fuente
Hay un par de convenciones en .NET para convertir objetos de un tipo a otro.
Pero estos métodos son mucho más lentos que los típicos
T.Parse(string)
, provocan el boxeo e involucran muchas asignaciones cada vez que desea convertir un solo valor.Para ValueString , elegí encontrar un método de análisis estático adecuado del tipo que usa reflexión, construir una expresión lambda llamándolo y almacenar en caché el delegado compilado para uso futuro (vea esta respuesta para un ejemplo).
También recurre a las formas que mencioné anteriormente si el tipo no tiene un método de análisis adecuado (consulte la sección de rendimiento en el archivo Léame).
var v = new ValueString("15"); // struct var i = v.As<int>(); // Calls int.Parse.
fuente