2010-08-02 19 views
74

Estoy tratando de usar TryParse para encontrar si el valor de la cadena es un número entero. Si el valor es un entero, omita el ciclo foreach. Aquí está mi código.Cómo usar int.TryParse con nullable int?

string strValue = "42 " 

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

intVal es una variable de tipo int? (Nullable INT). ¿Cómo puedo usar Tryparse con nullable int?

Respuesta

69

No se puede hacer esto sin utilizar otra variable, lamentablemente, porque el tipo de argumentos out tiene que coincidir exactamente con el parámetro.

como el código de Daniel, pero fija en términos del segundo argumento, el recorte, y evitando comparaciones con constantes booleanas:

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

@JonSkeet - strValue cna be null y el método Trim() daría lugar a una excepción. Solo digo. :) –

+3

@ShaktiPrakashSingh: No sabemos si 'strValue' podría ser nulo o no. Si proviene de un cuadro de texto, probablemente * no * puede ser nulo. Mi código no intenta abordar esto, pero realmente no sé si * debería * abordarlo o no. –

+0

¿por qué no invierte el 'si'? por ejemplo: 'if (int.TryParse (Request [" idParent "], out tmp)) idParent = tmp;' (de lo contrario es nulo) – Dementic

5

Se puede crear un método de ayuda para analizar un valor anulable.

Ejemplo de uso: Método

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

Ayudante:

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

Aquí hay una opción para un int anulable con TryParse

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

Me gusta esta versión ya que" 0 "devuelve 0 y" hola "devuelve nulo. En la respuesta aceptada, la distinción se pierde. –

+8

No me gusta su respuesta porque pierde el valor de retorno que indica el éxito/falla del análisis. Esa es una característica importante de un método Try *. – frattaro

+1

@frattaro Realmente no veo por qué esta respuesta podría ser mala. Pruebe el parseo devuelve 0 por defecto en caso de falla, en este ejemplo simplemente devuelve nulo en su lugar. – Edgar

20

No se pudo evitar que a mí mismo para producir una versión genérica. Uso a continuación.

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

También puede hacer un método de extensión para este propósito;

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

que he hecho esta una extensión del tipo object, pero podría ser igualmente bien en string. Personalmente, me gusta que estas extensiones de analizador estén disponibles en cualquier objeto, de ahí la extensión en object en lugar de string.

Ejemplo de uso:

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

El inconveniente sería que esto rompe con la sintaxis marcos para analizar los valores;

int.TryParse(input, out output)) 

pero me gusta la versión más corta de la misma (ya sea más legible o no ser objeto de discusión);

input.TryParse(out output) 
+0

Si haces esto, estás bloqueado en' TryParse' para 'int' solamente. ¿Qué hay de "doble"? O 'bool'? – FMM

+0

@FMM un poco tarde, pero escriba un método de extensión por separado si lo desea. no estoy seguro de lo que quiere decir "encerrado", los otros métodos de extensión tendrían una firma diferente –

+0

'T' es implícitamente convertible en' T? 'para las estructuras. Esto es excesivo. – FMM

Cuestiones relacionadas