¿Existe alguna función Parse () genérica que convierta una cadena en cualquier tipo usando parse?


91

Quiero convertir una cadena a un tipo genérico como into date, o longsobre 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.parseinternamente.

Respuestas:


132

System.Convert.ChangeType

Según su ejemplo, podría hacer:

int i = (int)Convert.ChangeType("123", typeof(int));
DateTime dt = (DateTime)Convert.ChangeType("2009/12/12", typeof(DateTime));

Para satisfacer su requisito de "tipo de devolución genérico", puede escribir su propio método de extensión:

public static T ChangeType<T>(this object obj)
{
    return (T)Convert.ChangeType(obj, typeof(T));
}

Esto le permitirá hacer:

int i = "123".ChangeType<int>();

fresco, pero lo extraño de su nombre changetype, así que yo pensaba que esta función hace algún tipo de molde y no analiza
— Karim

7
MSDN dice que es simplemente un contenedor que encuentra el método de conversión correcto en el objeto de origen, lo que requiere que implemente la interfaz IConvertible.
— Ani

Si necesita implementarse, IConvertable¿no debería restringir también el T, es decir T ChangeType<T>(this object obj) where T : IConvertable?
— Liam

2
@Liam: No, objdebe ser así IConvertible, pero no hay forma de especificarlo en tiempo de compilación.
— Ani

si necesito algo como TryChangeType que devuelva nulo o falso en caso de error? ¿Solo capturando una excepción?
— Hopeless

21

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;
           }

En mi humilde opinión, esta es la mejor respuesta porque también contiene el aspecto "anulable"
— Ole Albers

¿Existe una razón específica por la que está utilizando TypeDescriptorpara tipos que aceptan valores NULL y Convert.ChangeTypepara los que no aceptan valores NULL? Todo este trybloque se puede reducir solo a TypeConverter2 líneas de código y funcionará tanto para nulos como para no nulos.
— IMujagic


8

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);
    }
}

0

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.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.