2009-12-30 15 views
32

considerar los siguientes dos piezas de código:C#: Code Contracts frente a la validación de parámetros normales

public static Time Parse(string value) 
    { 
     string regXExpres = 
      "^([0-9]|[0-1][0-9]|2[0-3]):([0-9]|[0-5][0-9])$|^24:(0|00)$"; 
     Contract.Requires(value != null); 
     Contract.Requires(new Regex(regXExpres).IsMatch(value)); 
     string[] tokens = value.Split(':'); 
     int hour = Convert.ToInt32(tokens[0], CultureInfo.InvariantCulture); 
     int minute = Convert.ToInt32(tokens[1], CultureInfo.InvariantCulture); 
     return new Time(hour, minute); 
    } 

y

public static Time Parse(string value) 
    { 
     if (value == null) 
     { 
      throw new ArgumentNullException("value"); 
     } 
     string[] tokens = value.Split(':'); 
     if (tokens.Length != 2) 
     { 
      throw new FormatException("value must be h:m"); 
     } 
     int hour = Convert.ToInt32(tokens[0], CultureInfo.InvariantCulture); 
     if (!(0 <= hour && hour <= 24)) 
     { 
      throw new FormatException("hour must be between 0 and 24"); 
     } 
     int minute = Convert.ToInt32(tokens[1], CultureInfo.InvariantCulture); 
     if (!(0 <= minute && minute <= 59)) 
     { 
      throw new FormatException("minute must be between 0 and 59"); 
     } 
     return new Time(hour, minute); 
    } 

Yo personalmente prefiero la primera versión porque el código es mucho más claro y más pequeños, y los contratos pueden ser desactivados fácilmente. Pero la desventaja es que Visual Studio Code Analysis culpa de que debería verificar el valor del parámetro para null y los contratos del constructor no se dan cuenta de que la expresión regular asegura que el minuto y la hora están dentro de los límites establecidos.

Así que termino teniendo un montón de advertencias erróneas y no veo ninguna forma de validar valores de cadena con contratos sin terminar arrojando FormatExceptions aparte de una validación RegEx.

¿Alguna sugerencia de cómo resolvería esto y situaciones equivalentes mediante el uso de contratos de código?

+1

Te das cuenta de que podría volver a escribir el segundo ejemplo de usar la misma expresión regular, ¿verdad? Eso haría que ambos ejemplos sean más similares que no. –

Respuesta

21

Con el fin de deshacerse de las advertencias puede utilizar Contract.Assume

+0

este tipo de soluciona mi problema. Si agrego las siguientes líneas al frente de la declaración de devolución, todas las advertencias incorrectas desaparecerán. Lo único que todavía no me gusta es que estas líneas de algún modo están explotando el código. Pero supongo que es imposible que los contratos de código obtengan el significado de las expresiones regulares. Contract.Assume (0 <= hora && hora <= 24); Contract.Assume (0 <= minuto && minute <= 59); – steveee

+15

@steveee, siempre debe dividir los contratos en las conjunciones, de modo que 'Contract.Assume (0 <= hour && hour <= 24);' se convierte en 'Contract.Assume (0 <= hour); Contract.Assume (hora <= 24); ' – porges

+0

@Porges ¿hay algún documento que explique por qué? –

Cuestiones relacionadas