2009-12-30 9 views
32

considerare le seguenti due pezzi di codice:C#: Code Contracts vs. normale convalida dei parametri

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

e

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

Io personalmente preferisco la prima versione perché il codice è molto più chiara e più piccolo, e i Contratti possono essere facilmente disattivati. Ma lo svantaggio è che Visual Studio Code Analysis incolpa che dovrei controllare il valore del parametro per null e che i Contratti del costruttore non si rendono conto che la regex assicura che il minuto e l'ora siano all'interno dei limiti specificati.

Quindi finisco per ricevere molti avvisi errati e non vedo alcun modo per convalidare i valori stringa con i contratti senza dover rilasciare FormatExceptions oltre alla convalida RegEx.

Qualche suggerimento su come risolvere questa situazione e situazioni equivalenti utilizzando i contratti di codice?

+1

Ti rendi conto che si potrebbe riscrivere il secondo esempio di utilizzare la stessa espressione regolare, giusto? Ciò renderebbe entrambi gli esempi più simili. –

risposta

21

Al fine di sbarazzarsi di avvisi è possibile utilizzare Contract.Assume

+0

questo tipo risolve il mio problema. Se aggiungo le seguenti righe davanti alla dichiarazione di ritorno, tutti gli avvisi sbagliati sono andati. L'unica cosa che ancora non mi piace davvero è che queste righe stanno in qualche modo facendo esplodere il codice. Ma immagino sia impossibile per i contratti di codice ottenere il significato di espressioni regolari. Contratto.Assume (0 <= ora && ora <= 24); Contratto.Assume (0 <= minuto && minuto <= 59); – steveee

+15

@steveee, dovresti sempre dividere i contratti sulle congiunzioni, in modo che 'Contract.Assume (0 <= hour && hour <= 24);' diventa 'Contract.Assume (0 <= hour); Contratto.Assume (ora <= 24); ' – porges

+0

@Porges c'è un documento che spiega perché? –

Problemi correlati