J'essaie de démontrer les invariants dans les contrats de code, et j'ai pensé donner un exemple de liste de chaînes triée. Il maintient un tableau en interne, avec un espace libre pour les ajouts etc - tout comme List<T>
, fondamentalement. Quand il a besoin d'ajouter un élément, il insère dans le tableau, etc. je me suis dit que j'avais trois invariants:Comment est-ce que je peux être libre dans le code d'un objet invariant?
- Le nombre doit être raisonnable: non négatif et au plus aussi grand que la taille du tampon
- Tout dans la partie inutilisée de la mémoire tampon doit être nul
- Chaque élément de la partie utilisée du tampon doit être au moins aussi « grand » comme l'élément avant qu'il
maintenant, j'ai essayé de mettre en œuvre de cette façon:
[ContractInvariantMethod]
private void ObjectInvariant()
{
Contract.Invariant(count >= 0 && count <= buffer.Length);
for (int i = count; i < buffer.Length; i++)
{
Contract.Invariant(buffer[i] == null);
}
for (int i = 1; i < count; i++)
{
Contract.Invariant(string.Compare(buffer[i], buffer[i - 1]) >= 0);
}
}
Malheureusement, ccrewrite
désorganise les boucles.
La documentation de l'utilisateur indique que la méthode doit simplement être une série d'appels à Contract.Invariant
. Dois-je vraiment réécrire le code comme quelque chose comme ça?
Contract.Invariant(count >= 0 && count <= buffer.Length);
Contract.Invariant(Contract.ForAll
(count, buffer.Length, i => buffer[i] == null));
Contract.Invariant(Contract.ForAll
(1, count, i => string.Compare(buffer[i], buffer[i - 1]) >= 0));
C'est un peu moche, même si cela fonctionne. (C'est beaucoup mieux que ma précédente tentative, attention à vous.)
Mes attentes sont-elles déraisonnables? Mes invariants sont-ils déraisonnables?
(également demandé comme question in the Code Contracts forum. Je vais ajouter des réponses pertinentes ici moi-même.)
Apparemment, vous ne pouvez pas être aussi libre que la boucle se déroule./rimshot –
La chose bizarre est que la * première * boucle est ok ... mais la seconde ne l'est pas. Cela peut s'avérer être un bug dans ccrewrite, bien sûr. –
(Je suppose qu'il capture tout le code avant l'appel à Contract.Invariant ...) –