ReSharper – Possibile assegnazione nullo quando si utilizza Microsoft.Contracts

Esiste un modo per indicare a ReSharper che un riferimento null non si verificherà a causa del controllo Design-by-Contract? Ad esempio, il seguente codice genererà l’avviso ( Possible 'null' assignment to entity marked with 'NotNull' attribute ) in ReSharper nelle righe 7 e 8:

 private Dictionary _Lookup = new Dictionary(); public void Foo(string s) { Contract.Requires(!String.IsNullOrEmpty(s)); if (_Lookup.ContainsKey(s)) _Lookup.Remove(s); } 

Ciò che è davvero strano è che se si rimuove la riga Contract.Requires(...) , il messaggio ReSharper scompare.

Aggiornare

Ho trovato la soluzione tramite ExternalAnnotations che è stata menzionata anche da Mike in basso. Ecco un esempio di come farlo per una funzione in Microsoft.Contracts:

  • Creare una directory denominata Microsoft.Contracts nella directory ReSharper ExternalAnnotations .
  • Quindi, crea un file chiamato Microsoft.Contracts.xml e compilalo in questo modo:

      0     
  • Riavvia Visual Studio e il messaggio scompare!

Nota : dall’attuale EAP R # 8.0, questa funzionalità è inclusa.


Ecco la soluzione per la versione corrente (cioè .NET 4.0) dei Contratti di codice:

All’interno ...\ExternalAnnotations\mscorlib\Contracts.xml , aggiungere quanto segue:

      0        0        0        0        0        0        0        0        0        0     

Vorrei aggiungere che per le persone che scrivono i propri metodi di asserzione e simili, è ansible includere questi attributi senza un file XML esterno. In Visual Studio, vai a ReSharper > Options > Code Annotations e fai clic sul pulsante Copy default implementation to clipboard . Quindi crea un nuovo file (ovunque nella tua soluzione) e incolla il codice dagli Appunti. Ora puoi creare metodi come questo:

 public class Require { [AssertionMethod] public static void That( [AssertionCondition(AssertionConditionType.IS_TRUE)] bool requiredCondition, string message = null) { ... } ... } 

Ora qualsiasi chiamata a Require.That(a != null) indicherà a ReSharper che non è ansible superare questa riga se a è nullo. A differenza della tecnica ExternalAnnotations, questo funzionerà per chiunque usi i tuoi metodi, senza alcun lavoro aggiuntivo da parte loro.

Aggiornare

Il resharper ha cambiato il modello di annotazione del contratto a partire dalla versione 7. Ecco come sarà il metodo sopra riportato ora:

 public class Require { [ContractAnnotation("requiredCondition:false => halt")] public static void That( bool requiredCondition, string message = null) { ... } ... } 

Penso che tu possa ma non è banale. Dai un’occhiata alla guida in linea di Resharper per l’annotazione del codice

Hanno annotato le classi BCL e il framework NUnit (e altro ancora) per migliorare le capacità di ispezione del codice Resharpers.

Ad esempio con il NUnit afferma di aver annotato un AssertionMethodAttribute. Questo dice al controllo del codice Resharpers che se hai superato Assert.IsNotNull (foo); allora foo non deve essere nullo e non produrrà più l’avviso “Possibile ‘null’ assegnazione …”.

È ansible produrre un file XML annotando il metodo Contracts.Requires per indicare che è proprio come un Assert.

Il motivo per cui il messaggio scompare quando si rimuove l’asserzione è che R # funziona in modalità “ottimistica” per impostazione predefinita. Presume che tutto sia non nullo finché non si fa qualcosa che indica che può effettivamente essere nullo. Questo è ciò che accade quando aggiungi la chiamata a String.IsNullOrEmpty . Stai affermando che s potrebbe effettivamente essere nullo. Semplicemente non è a conoscenza del fatto che il metodo Contract.Requires fermerà l’esecuzione in questo caso, ma che hai risolto con l’annotazione.

In R # 5.0 è ansible passare a una modalità pessimistica che presuppone il peggiore in ogni angolo.

Ho preso l’XML di Porges e aggiunto annotazioni per i metodi Assert e Assume. Userò questa risposta wiki nel caso in cui altre persone vogliano aggiungere altri metodi.

      0        0        0        0        0        0        0        0        0        0     

Il resharper ha cambiato il modello di annotazione del contratto a partire dalla versione 7.

Hai bisogno di un file diverso. La nuova posizione (credo solo per le app Metro) è: “C: \ Programmi (x86) \ JetBrains \ ReSharper \ v7.1 \ Bin \ ExternalAnnotations \ .NETCore \ System.Diagnostics.Contracts \ Contracts.xml”

Sto usando Visual Studio 2012 e. Net 4.5 e Resharper 7.1.

Soddisfare:

     condition:false=>halt      condition:false=>halt      condition:false=>halt      condition:false=>halt      condition:false=>halt      condition:false=>halt      condition:false=>halt      condition:false=>halt      condition:false=>halt      condition:false=>halt    

TL; DR – Aggiungi il simbolo di compilazione condizionale CONTRACTS_FULL al tuo progetto.

Il metodo Contract.Requires(...) è vuoto e disabilitato, a meno che non si abiliti e si usi il rewriter di Contatti di codice. Eseguendo manualmente il rewriter o (solitamente) abilitandolo attraverso le proprietà del progetto Visual Studio, si manterrà il codice Contract.Requires(...) nei binari compilati e riscritti. Sai che il codice funzionerà, e ignorando l’avviso di Resharper, puoi eseguirlo e testarlo.

Qual è il problema allora? Resharper non sa che i contratti di codice sono in esecuzione, dal momento che sono in realtà solo iniettati a (post) tempo di compilazione. Agli occhi di Resharper, è disabilitato nello stesso modo in cui funziona il simbolo del preprocessore DEBUG e in che modo Visual Studio ignora le aree del codice che non faranno parte dei binari compilati.

 #ifdef DEBUG Console.WriteLine("I'm in DEBUG mode, so this is probably a Debug build."); #else Console.WriteLine("Let's assume this is a Release build."); #endif 

Secondo il manuale utente dei Contratti di codice (capitolo 2, primo paragrafo) e il codice sorgente in ContractExtensions.cs (incluso nella cartella di installazione dei Contratti di codice), CONTRACTS_FULL deve essere impostato prima di compilarlo. I metodi Contratto sono effettivamente implementati con [ConditionalAttribute("CONTRACTS_FULL")] e ignorati (non inclusi in fase di compilazione) a meno che il flag non sia impostato. Resharper rispetta questo flag e presume che la funzione non verrà eseguita a meno che non sia impostata.

 [ConditionalAttribute("CONTRACTS_FULL")] public static void Requires(bool condition) { ... } 

Soluzione: aggiungi il simbolo di compilazione condizionale CONTRACTS_FULL al tuo progetto. Vedi Utilizzo dei contratti di codice Visual Studio e con Resharper di Henning Krause.

http://sofit.miximages.com/c%23/ConditionalSymbol.png

Il team di Resharper è stato avvisato; L’analisi del codice non considera le impostazioni nella scheda delle proprietà del progetto “Contratti di codice” , Supporto dei Contratti Microsoft Code .