Esiste una funzione generica Parse () che convertirà una stringa in qualsiasi tipo utilizzando parse?


91

Voglio convertire una stringa in un tipo generico come into dateo in longbase al tipo restituito generico.

Fondamentalmente una funzione del genere Parse<T>(String)restituisce un elemento di tipo T.

Ad esempio, se è stato passato un int, la funzione dovrebbe essere eseguita int.parseinternamente.

Risposte:


132

System.Convert.ChangeType

Secondo il tuo esempio, potresti fare:

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

Per soddisfare il tuo requisito di "tipo restituito generico", potresti scrivere il tuo metodo di estensione:

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

Questo ti permetterà di fare:

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

bello, ma la cosa strana si chiama ChangeType, quindi penserei che questa funzione esegua una sorta di cast e non analizzi
Karim

7
MSDN dice che è semplicemente un wrapper che trova il giusto metodo di conversione sull'oggetto di origine, richiedendo che implementi l'interfaccia IConvertible.
Ani

Se deve essere implementato IConvertable, non dovresti anche vincolare il T, ie T ChangeType<T>(this object obj) where T : IConvertable?
Liam

2
@ Liam: No, objdeve essere così IConvertible, ma non c'è modo di specificarlo in fase di compilazione.
Ani

se ho bisogno di qualcosa come TryChangeType che restituisce null o false in caso di errore? Solo catturando l'eccezione?
Hopeless

21

Sembra che sia troppo tardi per rispondere a questo thread. Ma ecco la mia implementazione:

Fondamentalmente, ho creato un metodo Extention per la classe Object. Gestisce tutti i tipi, ovvero nullable, classi e struttura.

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

IMHO questa è la risposta migliore perché contiene anche l'aspetto "nullable"
Ole Albers

c'è un motivo specifico per cui stai usando TypeDescriptorper i tipi nullable e Convert.ChangeTypeper quelli non nullable? L'intero tryblocco può essere ridotto solo a TypeConverter2 righe di codice e funzionerà per entrambi, nullable e non nullable.
IMujagic


8

versione più pulita della risposta di 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

Esistono un paio di convenzioni in .NET per convertire oggetti di un tipo in un altro.

Ma questi metodi sono molto più lenti del normale T.Parse(string), causano la boxe e comportano molte allocazioni ogni volta che vuoi convertire un singolo valore.

Per ValueString , ho scelto di trovare un metodo di analisi statico adatto del tipo utilizzando la reflection, creare un'espressione lambda chiamandola e memorizzare nella cache il delegato compilato per un utilizzo futuro (vedere questa risposta per un esempio).

Funziona anche nei modi che ho menzionato sopra se il tipo non ha un metodo di analisi adatto (vedere la sezione sulle prestazioni nel file Leggimi).

var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.