2010-08-06 12 views
26

Ho giocato con la nuova classe System.Diagnostics.Contracts perché all'inizio sembrava molto utile. Metodi statici per verificare gli argomenti in entrata, i valori restituiti, ecc. Era un'interfaccia pulita e poteva sostituire molte istruzioni if-then e strumenti di libreria costruiti internamente.Utilità di System.Diagnostics.Contracts in questione

Tuttavia, sembra meno utile nella maggior parte delle situazioni di runtime. Da quello che posso dire, non genera un errore, quindi non posso prendere nulla per sapere se un contratto è fallito. Si apre una finestra di dialogo con l'errore. Se sto eseguendo un servizio wcf su una casella remota che raramente ha un aspetto umano ... come faccio a sapere se il contratto è fallito? Se non riesco a intrappolare il fatto che si sia verificato l'errore, come posso far sapere al chiamante del servizio che sono saltati?

Throw-Catch è in circolazione da un po ', non capisco perché i Contratti vogliano aggirare questo. Sto tentando di usare questa cosa in modo errato? Se è così, allora qualcuno mi dà una situazione di vita reale in cui un contratto di runtime ha un senso. Ken

+0

Probabilmente perché è nello spazio dei nomi Diagnostics che implica che non dovrebbe essere utilizzato per lo scopo previsto. Prova a dare un'occhiata ai contratti in codice oa qualcosa di simile. – Kane

+0

Pensavo che si trattasse di contratti in codice. È l'unico pezzo di codice in .Net 4.0 di cui sono a conoscenza. (senza contare ServiceContract o DataContract in WCF ... è diverso) –

+1

I contratti di codice sono in effetti situati all'interno dello spazio dei nomi 'System.Diagnostics'. Stai usando la cosa giusta. – Rich

risposta

36

Da quello che posso dire, non genera un errore quindi non riesco a prendere nulla per sapere se un contratto non è riuscito.

Se avete bisogno di lanciare una particolare eccezione per chiamare il codice per la cattura, allora si dovrebbe utilizzare i metodi o legacy Contract.Requires<TException> if-then-lanci seguito da Contract.EndContractBlock(). Lo faresti quando un altro codice si aspetta già e dipende dalle regolari eccezioni generate, per esempio.

Vedere Sezione 5.1: Convalida degli argomenti e contratti dello user manual per una spiegazione completa di quando utilizzare le diverse forme di precondizione.

Si apre una finestra di dialogo con l'errore.

Se Deselezionare "Affermare in caso di errore Contratto" nella scheda "Code Contracts" delle impostazioni di progetto, si otterrà un'eccezione reale gettato nel punto incriminato nel codice durante il debug, piuttosto che una finestra di dialogo. Questo non è per la cattura, tuttavia.

Throw-Catch è in circolazione da un po ', non capisco perché i Contratti vogliano aggirare questo. Sto tentando di usare questa cosa in modo errato? Se è così, allora qualcuno mi dà una situazione di vita reale in cui un contratto di runtime ha un senso.

Sezione 7.5: razionale per Runtime Comportamento e Sezione 7.6: ContractException del user manual spiegare perché funziona in questo modo.

L'idea è che non si dovrebbe mai aver bisogno di scrivere programmi che contengono una logica specifica che gestisce le violazioni del contratto. Non dovrebbero mai accadere nei programmi corretti e indicare un errore grave nel codice che deve essere risolto. Questo è simile a come dovresti evitare di catturare ArgumentNullException.

Si dovrebbero comunque presentare eccezioni regolari in circostanze eccezionali che non indicano errori nel codice stesso, ad esempio quando non è possibile trovare i file. Ciò consente al codice chiamante di gestire quella circostanza come appropriato.

Se sto eseguendo un servizio wcf su una casella remota che raramente ha un aspetto umano ... come potrei sapere che il contratto è fallito?

Preferibilmente, è necessario testare il software il più possibile prima di metterlo in uso, per assicurarsi che non violi mai contratti.

Se si ha una necessità specifica di sovrascrivere il comportamento di runtime, è possibile farlo scrivendo la propria classe di esecuzione del contratto. Vedere Sezione 7.7: Fornire una Classe runtime del contratto personalizzato dello user manual per ulteriori informazioni.

Edit: In risposta al commento qui sotto ...

Lei dice che ha lo scopo di trovare difetti nel codice, ma la maggior parte gli errori nel codice proviene da dati passati in da fonti esterne, non è colpa dei codici. E il software ha bisogno di entrambi, registra il fatto che qualcuno ha trasmesso dati non validi e dice loro che hanno trasmesso dati errati in modo che possano ripararli.

Presupposti sono contratti che definiscono quando un metodo è ammessi di essere chiamato, e sono destinati ad essere verificata da parte del chiamante al momento della chiamata al metodo. Il correttore di runtime inserisce i controlli appropriati nel codice chiamante, non nel metodo stesso. Se hai il correttore statico disponibile, ti indicherà ogni volta che non riuscirai a garantire le precondizioni prima di chiamare quel metodo.

Nella vostra situazione, i vostri metodi interni che elaborano i dati dovrebbero definire i presupposti che indicano il tipo di dati che consentono. Quando i dati vengono trasmessi da fonti esterne che non puoi controllare, devi convalidarli e gestirli nel solito modo; non vuoi usare contratti di codice per questo. Tuttavia, se ad esempio si dimentica di convalidare completamente tali dati, si verificherà una violazione del contratto quando si chiama il codice interno con le condizioni preliminari. Questo indica un bug nel proprio codice.

+0

Ricco, grazie per aver dedicato del tempo. Però non hai fatto un caso per l'utilità dei Contratti. Si dice che è destinato a trovare errori nel codice, ma la maggior parte dei guasti nel codice provengono da dati trasmessi da fonti esterne, non dai codici guasti. E il software ha bisogno di entrambi, registra il fatto che qualcuno ha trasmesso dati non validi e dice loro che hanno trasmesso dati errati in modo che possano ripararli. I contratti non sembrano consentirlo. I contratti statici (tempo di compilazione) hanno senso per me. I contratti di runtime, come implementati con il pacchetto Diagnostics, non sembrano risolvere nulla. Sto ancora cercando il caso d'uso. –

+2

Controlla la mia risposta aggiornata per la mia risposta. La risposta era troppo grande per essere pubblicata come commento. – Rich