2016-06-24 13 views
6

Sto provando a convertire da String a un tipo generico. Il tipo generico sarà un Int32, Int64, Boolean, doppio e così via ... Ho provato due approcci:Convertitore di tipo generico - TypeConverter o Convert.ChangeType

public static Boolean TryParse<T>(String source, out T value) { 

    TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); 

    try { 

    value = (T)converter.ConvertFromString(source); 
    return true; 

    } catch { 

    value = default(T); 
    return false; 

    } 

} 

public static Boolean TryChangeType<T>(Object source, out T value) { 

    try { 

    Type type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T); 

    value = (T)Convert.ChangeType(source, type); 
    return true; 

    } catch { 

    value = default(T); 
    return false; 

    } 

} 

Il secondo è più generico come si accetta un oggetto.

Sto anche considerando di passare un IFormatProvider in TryChangeType che verrebbe utilizzato in Convert.ChangeType per risolvere i problemi di cultura e così via.

Considerate meglio il secondo approccio?

In qualsiasi modo posso migliorare il mio codice?

+0

Possibile duplicato di [TypeConverter vs. Converti vs. TargetType.Parse] (http://stackoverflow.com/questions/7010669/typeconverter-vs-convert-vs-targettype-parse) –

risposta

2

Nel primo esempio è possibile sbarazzarsi del blocco catch try chiamando in anticipo CanConvertTo() e CanConvertFrom().

public static bool TryParse<T>(string source, out T value) 
{ 
    TypeConverter converter = TypeDescriptor.GetConverter(typeof (T)); 
    if (converter.CanConvertTo(typeof (T)) && converter.CanConvertFrom(typeof (string))) 
    { 
     value = (T)converter.ConvertFromString(source); 
     return true; 
    } 
    else 
    { 
     value = default (T); 
     returns false; 
    } 
} 

Nel secondo esempio perché non rendono ancora più generico e passano in un tipo generico?

Convert funziona solo se il tipo implementa l'interfaccia IConvertible in modo da poterlo verificare, dall'altra parte non garantisce che la conversione sia possibile.

 public static bool TryChangeType<T, TR>(T input, out TR output) where T : IConvertible 
    { 
     bool result = false; 
     try 
     { 
      Type type = Nullable.GetUnderlyingType(typeof(TR)); 
      output = (TR)Convert.ChangeType(input, type); 
      result = true; 
     } 
     catch(Exception) 
     { 
      output = default(TR); 
     } 
     return result; 
    } 

Sarebbe bello per catturare solo le eccezioni che conosci di:

  catch(InvalidCastException) 
     { 
      output = default(TR); 
      //Conversion is not unsupported 
     } 
      catch(FormatException) 
     { 
      output = default(TR); 
      //string input value was in incorrect format 
     } 
      catch(InvalidCastException) 
     { 
      output = default(TR); 
      //Conversion is not unsupported 
     } 
      catch(OverflowException) 
     { 
      output = default(TR); 
      //narrowing conversion between two numeric types results in loss of data 
     } 

Questo non potrebbe rispondere pienamente alla domanda, ma che stavi chiedendo possibili miglioramenti così ho pensato perché non.

+0

Sì, questo lo rende ancora più generico. Buon suggerimento –

0

Nel tuo primo esempio, TypeDescriptor.GetConverter(Type) può generare eccezioni, quindi spostarlo nel blocco try. Senza provarli personalmente, dai tuoi due approcci mi piace il secondo.

This post mostra un esempio di test per la convertibilità senza vantaggi di prestazioni try/catch e claims.

+0

Interessante ... Liberarmi del blocco Try Catch era qualcosa che volevo fare ... Non sapevo che fosse possibile. –

1

Il secondo è applicabile solo per i tipi IConvertible. Se questo è ciò che si vuole, si potrebbe desiderare di applicare un vincolo, troppo (ChangeType un'eccezione per i tipi non convertibili in ogni caso):

public static Boolean TryChangeType<T>(Object source, out T value) 
    where T : IConvertible 
{ 
    // ... 
} 

Il primo è più generale, TypeConverter viene utilizzato quando il. È necessario utilizzare il modello di componente NET. Ad esempio, nei progettisti, i convertitori di tipi vengono utilizzati per convertire i valori da una stringa nella griglia delle proprietà. Ma si dovrebbe aggiungere un piccolo ulteriore controllo anche qui:

if (!converter.CanConvertFrom(typeof(string))) 
    return false; 

Inoltre, vorrei ricordare che si dovrebbe utilizzare il metodo ConvertFromInvariantString se non si vuole problemi con le varie impostazioni della regione (in caso di valori in virgola mobile, ad esempio) ...

+0

Informazioni su ConvertFromInvariantString che è un buon consiglio ... Avevo problemi con la conversione dei doppi con "." o "," ... Ma usando la seconda opzione potrei passare un IFormatProvider ... Questo risolve il problema nel secondo esempio, giusto? –

+0

Sì, usare una coltura specifica risolve anche il problema. Btw, puoi anche convertire da qualsiasi sorgente 'object' qui. Basta usare il metodo 'CanConvertFrom (Type)'. – taffer

Problemi correlati