¿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.

Karim
fuente

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>();
Y yo
fuente
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;
           }
Pranay Deep
fuente
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
9

System.Convert.ChangeTypeno se convierte a ningún tipo. Piense en lo siguiente:

  • tipos que aceptan valores NULL
  • enumeraciones
  • Guid, etc.

Estas conversiones son posibles con esta implementación de ChangeType .

Alex Siepman
fuente
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);
    }
}
Eonasdan
fuente
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.
Şafak Gür
fuente