2010-08-02 8 views
74

Sto cercando di utilizzare TryParse per trovare se il valore stringa è un numero intero. Se il valore è un numero intero, salta il ciclo foreach. Ecco il mio codice.Come utilizzare int.TryParse con int nullo?

string strValue = "42 " 

if (int.TryParse(trim(strValue) , intVal)) == false 
{ 
    break; 
} 

intVal è una variabile di tipo int? (Nullable INT). Come posso usare Tryparse con nullable int?

risposta

69

Purtroppo non è possibile farlo senza utilizzare un'altra variabile, perché il tipo di argomenti out deve corrispondere esattamente al parametro.

Come il codice di Daniel, ma fissa in termini di secondo argomento, rifilatura, ed evitando il confronto con costanti booleane:

int tmp; 
if (!int.TryParse(strValue.Trim(), out tmp)) 
{ 
    break; 
} 
intVal = tmp; 
+0

@JonSkeet - strValue cna essere nullo e il metodo Trim() genererebbe un'eccezione. Sto solo dicendo :) –

+3

@ShaktiPrakashSingh: Non sappiamo se 'strValue' potrebbe essere nullo o no. Se proviene da una casella di testo, probabilmente * non può * essere nullo. Il mio codice non tenta di risolvere questo problema, ma non sappiamo davvero se * dovrebbe * affrontarlo o meno. –

+0

perché non invertire il 'se'? es .: 'if (int.TryParse (Request [" idParent "], out tmp)) idParent = tmp;' (altrimenti è nullo) – Dementic

5

è possibile creare un metodo di supporto per analizzare un valore nullable.

Esempio di utilizzo:

int? intVal; 
if(!NullableInt.TryParse("42", out intVal)) 
{ 
    break; 
} 

Helper Metodo:

public static class NullableInt 
{ 
    public static bool TryParse(string text, out int? outValue) 
    { 
     int parsedValue; 
     bool success = int.TryParse(text, out parsedValue); 
     outValue = success ? (int?)parsedValue : null; 
     return success; 
    } 
} 
101

Ecco un'opzione per un int nullable con TryParse

public int? TryParseNullable(string val) 
{ 
    int outValue; 
    return int.TryParse(val, out outValue) ? (int?)outValue : null; 
} 
+3

Mi piace questa versione poiché" 0 "restituisce 0 e" ciao "restituisce null. Nella risposta accettata, la distinzione è persa. –

+8

Non mi piace la sua risposta perché perde il valore di ritorno che indica il successo/fallimento del parse. Questa è una caratteristica importante di un metodo Try *. – frattaro

+1

@frattaro Non vedo davvero perché questa risposta potrebbe essere male. Prova l'analisi restituisce 0 per impostazione predefinita in caso di errore, in questo esempio restituisce semplicemente null. – Edgar

20

non poteva impedire a me stesso di produrre una versione generica. Uso di seguito.

public class NullableHelper 
    { 
     public delegate bool TryDelegate<T>(string s, out T result); 

     public static bool TryParseNullable<T>(string s, out T? result, TryDelegate<T> tryDelegate) where T : struct 
     { 
      if (s == null) 
      { 
       result = null; 
       return true; 
      } 

      T temp; 
      bool success = tryDelegate(s, out temp); 
      result = temp; 
      return success; 
     } 

     public static T? ParseNullable<T>(string s, TryDelegate<T> tryDelegate) where T : struct 
     { 
      if (s == null) 
      { 
       return null; 
      } 

      T temp; 
      return tryDelegate(s, out temp) 
         ? (T?)temp 
         : null; 
     } 
    } 


bool? answer = NullableHelper.ParseNullable<bool>(answerAsString, Boolean.TryParse); 
3

È anche possibile creare un metodo di estensione per questo scopo;

public static bool TryParse(this object value, out int? parsed) 
{ 
    parsed = null; 
    try 
    { 
     if (value == null) 
      return true; 

     int parsedValue; 
     parsed = int.TryParse(value.ToString(), out parsedValue) ? (int?)parsedValue : null; 
     return true; 
    } 
    catch (Exception) 
    { 
     return false; 
    } 
} 

Ho fatto questo un'estensione del tipo object, ma si potrebbe anche su string. Personalmente mi piace che queste estensioni parser siano disponibili su qualsiasi oggetto, quindi l'estensione su object anziché string.

Esempio di utilizzo:

[TestCase("1", 1)] 
[TestCase("0", 0)] 
[TestCase("-1", -1)] 
[TestCase("2147483647", int.MaxValue)] 
[TestCase("2147483648", null)] 
[TestCase("-2147483648", int.MinValue)] 
[TestCase("-2147483649", null)] 
[TestCase("1.2", null)] 
[TestCase("1 1", null)] 
[TestCase("", null)] 
[TestCase(null, null)] 
[TestCase("not an int value", null)] 
public void Should_parse_input_as_nullable_int(object input, int? expectedResult) 
{ 
    int? parsedValue; 

    bool parsingWasSuccessfull = input.TryParse(out parsedValue); 

    Assert.That(parsingWasSuccessfull); 
    Assert.That(parsedValue, Is.EqualTo(expectedResult)); 
} 

Lo svantaggio è che questo rompe con la sintassi quadri per l'analisi dei valori;

int.TryParse(input, out output)) 

ma mi piace la versione più corta di esso (se è più leggibile o non potrebbe essere oggetto di discussione);

input.TryParse(out output) 
+0

Se lo fai, sei bloccato in' TryParse' solo per 'int'. Che ne pensi di 'double'? O "bool"? – FMM

+0

@FMM un po 'in ritardo ma, scrivi un metodo di estensione separato per quelli se li vuoi. non è sicuro di cosa intendi "locked in" gli altri metodi di estensione avrebbero una diversa firma –

+0

'T' è implicitamente convertibile in' T? 'per le strutture. Questo è eccessivo. – FMM

Problemi correlati