2015-11-11 20 views
6

Sto lavorando con qualche codice legacy in questo momento che di solito utilizzava try + catch in combinazione con Convert.ToDecimal(someString) (ad esempio) per provare e convertire stringhe in decimali . Per alcuni motivi devo usare l'impostazione che - quando si esegue il debug - mi fermo ad ogni eccezione lanciata (non solo all'utente non gestita) e quindi questo è diventato fastidioso e l'ho modificato per utilizzare i metodi TryParse ogni volta che è possibile.Un modo più elegante di scoprire se posso convertire un valore in un certo tipo

momento sto facendo una situazione in cui c'è un valore e un obiettivo objectType, e tutto quello che voglio sapere è se posso convertire il valore nel tipo di destinazione. In questo momento questo è fatto come segue:

try 
{ 
    Convert.ChangeType(val, targetType); 
} 
catch 
{ 
    // Do something else 
} 

Il risultato effettivo non è importante e non viene utilizzato ulteriormente.

Mentre questo codice funziona in questo momento, come ho detto, diventa un po 'fastidioso e quindi mi chiedo: C'è un altro modo di fare quanto sopra senza dover rilevare un'eccezione?

ho pensato a qualcosa di simile a IsAssignableFrom su un Type, ma questo non sembra essere applicabile nel mio caso (non voglio assegnare, voglio sapere se esplicitamente conversione è possibile).

+0

Mi piace sapere in quale contesto il codice che si utilizza viene effettivamente utilizzato perché l'uso di Convert.ChangeType [odori] (https://en.wikipedia.org/wiki/Code_smell) non valido – Dbuggy

+0

@Dbuggy Il codice è pieno purtroppo con gli odori del codice, quindi scommetto che hai ragione. È in un tipo 'ComboBox' (Forms) chiamato' BindingComboBox' che ottiene una proprietà 'DataSource' (l'intera cosa è IMHO non necessaria, ma non ho il tempo di cambiare completamente tutti i suoi usi in questo momento). Quindi il codice sopra riportato è usato per verificare se 'SelectedValue' è" valido "w.r.t. la proprietà 'DataType' dell'origine dati sottostante. Dato che questi ComboBox personalizzati compaiono ovunque, ottengo MOLTE eccezioni lanciate tutto il tempo. – InvisiblePanda

+1

Forse hai creato un duplicato in [http://stackoverflow.com/questions/2961656/generic-tryparse](http://stackoverflow.com/questions/2961656/generic-tryparse) – Dbuggy

risposta

3

Se vuoi dire la fusione, che è possibile utilizzare is parole chiave come:

object someObject = GetSomeObject(); 
if (someObject is string) 
{ 
    .. 
} 

Ma nota, che fusione e Convert.ChangeType non sono la stessa. Ad esempio, non è possibile lanciare una stringa in un int:

string numberString = "15"; 
int number = (int)numberString; 

ma è possibile utilizzare ChangeType per esso:

string numberString = "15"; 
int number = (int)Convert.ChangeType(numberString, typeof(int)); 

EDIT:

Se è necessario testare una variabile per essere convertibile in un tipo specifico, quindi perché non solo avvolgere try-catch con Convert.ChangeType in un metodo di prova:

public bool IsConvertibleTo<T>(object value) 
{ 
    try 
    { 
     T convertedValue = (T)Convert.ChangeType(value, typeof(T)); 
     return true; 
    } 
    catch (InvalidCastException) 
    { 
     return false; 
    } 
    catch (FormatException) 
    { 
     return false; 
    } 
    catch (OverflowException) 
    { 
     return false; 
    } 
} 
+0

Ehi, scusate, non ero più chiaro! Hai ragione e dovrei riformulare leggermente la mia domanda. Ciò che intendo è in realtà "conversione esplicita" (potrebbero esserci diversi tipi numerici coinvolti, quindi non posso usare "is" affatto), e questo probabilmente cambia un po 'l'esito della domanda. – InvisiblePanda

+0

Non sono abbastanza sicuro di cosa intendi dicendo che è impossibile usare 'is' poiché sono coinvolti diversi tipi di numeri. A condizione che tu abbia 'object value = 2', expression' value is int' restituirà 'true'. Allo stesso tempo l'espressione, ad esempio, 'value is decimal', restituisce' false', ma non è possibile eseguire il cast di 'value' su' decimal' senza prima eseguire il cast di 'int':' (decimal) value' fallirà , mentre '(decimale) (int) valore 'avrà successo. –

+0

Non riesco a usare 'is' perché in quel momento conosco solo il tipo di destinazione come' Type'. Ma hai ragione, è molto probabile che io non possa aggirare un blocco 'catch', anche se è quello che voglio evitare. Giocherò un po 'di più con la classe 'TypeConverter' e i suoi metodi, ma se non funziona, accetterò la tua risposta :) – InvisiblePanda

0

Se si desidera controllare il tipo di val, è necessario utilizzare parole chiave is come questo,

if (val is targetType) { 
    ... 
} 

Se si desidera convertire val a digitare targetType, è necessario utilizzare parole chiave as come questo,

targetType result = val as targetType; 

if (result != null) { 
    ... 
} 

Entrambi non lanciano un'eccezione!

Link: https://msdn.microsoft.com/zh-cn/library/cscsdfbt.aspx

+0

Sfortunatamente, 'Convert.ChangeType' fa più del parametro' as', il che significa che se 'come'fails,' ChangeType' potrebbe avere successo. – Oliver

+0

@Oliver Penso che sia pazzesco se non si tratta di operazioni di boxing o unboxing nel ramo fallito. – Itachi

+0

Ecco un esempio che fallirebbe con 'as', ma con' Convert.ChangeType': '' Convert.ChangeType ("123", typeof (int)); ', perché non getta semplicemente l'oggetto dato, invece (da cui il nome) lo converte (se possibile). – Oliver

2

ti darò una soluzione per eccezioni "nascondere". A volte è necessario rilevare un'eccezione e come hai detto è fastidioso perché il debugger si fermerà su ogni eccezione.Lo so, ma c'è un modo di fare che:

[DebuggerStepThrough] 
public bool CanChangeType(this object instance, Type targetType) 
{ 
    try 
    { 
    Convert.ChangeType(val, targetType); 
    return true; 
    } 
    catch 
    { 
    return false; 
    } 
} 

Il trucco è il -attribute DebuggerStepThrough.

Ma tieni presente che non sarai mai in grado di eseguire il debug in tale metodo. Non c'è correzione di bug senza rimuovere l'attributo. Sapendo che un metodo dovrebbe essere breve - molto breve e ovviamente dovrebbe essere libero da tutti gli errori.

Ho gli stessi problemi con le classi Udp che generano un'eccezione alla chiusura. L'estrazione di questo codice breve in un metodo separato che non contiene errori funziona correttamente.

0

L'ipotesi iniziale è giusta.

public static bool CanChangeType(Type type) 
    { 
     return typeof (IConvertible).IsAssignableFrom(type); 
    } 

è il modo giusto per controllare per tipo se Convert.ChangeType funzionerà o meno (come il messaggio di eccezione di solito indica). Non sei sicuro del motivo per cui sei contrario a questo metodo a causa del "Assegna" nel suo nome. Sta solo eseguendo alcuni controlli sul tipo. A parte questo, in realtà non esegue alcun assegnamento.

+0

Ciao Andreas, la domanda non riguarda se il metodo 'ChangeType' è applicabile, ma piuttosto il suo successo nella conversione del valore reale. Vedi la risposta accettata e la risposta di @ Verarind :) – InvisiblePanda

+0

@InvisiblePanda ah ok allora. "Il risultato attuale non è importante e non viene utilizzato ulteriormente Mentre questo codice funziona in questo momento, come ho detto, diventa un po 'fastidioso e quindi mi chiedo: c'è un altro modo di fare quanto sopra senza dover prendere un eccezione?" sembrava desiderare un'altra risposta, perché il mio metodo può essere usato per dire se è possibile o meno la conversione – Dbl