2013-08-01 14 views
5

Recentemente ho installato gli strumenti Contratti di codice (Contratti di codice per .NET) e le estensioni dell'Editor dei contratti di codice VS2012 e sto avendo qualche problema a far funzionare il controllo statico propriamente.Controllore statico dei contratti di codice apparentemente inconsapevole di Contract.Ensures di ReadOnlyCollection <T> costruttore

Quando eseguo checker statico Code Contracts' il seguente codice (con la seconda ipotesi commentata)

using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Diagnostics.Contracts; 

public class TestClass 
{ 
    public ReadOnlyCollection<byte> Foo() 
    { 
     Contract.Ensures(Contract.Result<ReadOnlyCollection<byte>>().Count == 4); 

     IList<byte> list = new byte[4]; 
     Contract.Assume(list.Count == 4); 
     var returnValue = new ReadOnlyCollection<byte>(list); 
     //Contract.Assume(returnValue.Count == 4); 
     return returnValue; 
    } 
} 

ottengo un "garantisce non provata" lettura avvertimento:

CodeContracts: assicura unproven: Contract.Result<ReadOnlyCollection<byte>>().Count == 4

Afferma che l'assicurazione del metodo Foo non è provata. Tuttavia, quando mouse constructor di ReadOnlyCollection<T>, posso dire che la proprietà dell'oggetto costruito Count è garantito per essere uguale al Count proprietà del parametro list: Constructor mouseover

Cioè, il correttore statica dovrebbe essere in grado di dire che returnValue.Count == 4 (cioè l'assicurazione di Foo) è vera. Se disattengo la seconda ipotesi, l'avvertimento scompare, ma partendo dal presupposto che l'assicurazione del mio metodo tenga vere sconfitte allo scopo del controllore statico.

Penso che il problema potrebbe essere che solo l'estensione editor di è a conoscenza del gruppo di riferimento del contratto contenente le assicura per il costruttore (mscorlib.Contracts.dll), in modo che elenca i contratti che il correttore statica è a conoscenza.

Ho tentato di armeggiare con l'impostazione di percorsi di libreria a contratto extra del progetto senza alcun risultato, e non penso che quello sia il modo giusto per risolvere il problema.

Ho ragione nel ritenere che il controllo statico non è configurato correttamente con l'assembly di riferimento del contratto o mi manca qualcos'altro? Se ho ragione, come andrei a risolvere la configurazione?

sto usando

  • Visual Studio Ultimate 2012 Update 3
  • Codice Contratti versione Strumenti 1.5.60502.11
  • Codice Contratti versione Editor estensioni VS2012 1.5.64024.12

Modifica: Il controllo statico sembra trovare gli assembly di riferimento del contratto e funziona come prima me lo aspettavo con altre classi e persino metodi della classe ReadOnlyCollection<T>. L'analisi statica di, ad esempio, il seguente metodo funziona bene.

public int Boo() 
    { 
     Contract.Ensures(-1 <= Contract.Result<int>()); 
     Contract.Ensures(Contract.Result<int>() < 4); 

     IList<byte> list = new byte[4]; 
     var collection = new ReadOnlyCollection<byte>(list); 
     Contract.Assume(collection.Count == 4); 
     return collection.IndexOf(0); 
    } 

è necessaria L'assunzione immobile Count perché si accerta del costruttore ancora non funziona. Le garanzie del metodo IndexOf, d'altro canto, funzionano molto bene.

Ora tutto quello che chiedo è il motivo per il controllo statico non riconosce le assicura del costruttore ReadOnlyCollection<T>. Potrebbe essere un bug nell'analizzatore statico?

risposta

0

contratti codice potrebbe essere alzando questo avviso perché la proprietà Count della classe ReadOnlyCollection non è costante.

Nell'esempio che segue, ho creare un'istanza della classe ReadOnlyCollection, passando una lista contenente 4 interi. La proprietà Count restituisce un valore di 4. Ho successivamente modificare l'elenco avvolto da ReadOnlyCollection cancellando e aggiungendo 3 interi. La proprietà Count della ReadOnlyCollection ora restituisce un valore pari a 3 senza di me aver toccato ReadOnlyCollection.

IList<byte> list = new List<byte>() { 1, 2, 3, 4 }; 
var collection = new ReadOnlyCollection<byte>(list); 

// Outputs: 1, 2, 3, 4. 
foreach (var item in collection) 
{ 
    Console.WriteLine(item); 
} 

list.Clear(); 
list.Add(5); 
list.Add(6); 
list.Add(7); 

// Outputs: 5, 6, 7 
Console.WriteLine(); 
foreach (var item in collection) 
{ 
    Console.WriteLine(item); 
} 

Console.ReadKey();