Ich versuche, Invarianten in Code Contracts zu demonstrieren, und ich dachte, ich würde ein Beispiel für eine sortierte Liste von Zeichenfolgen geben. Es verwaltet ein Array intern, mit Platz für Ergänzungen usw. - genau wie List<T>
, im Grunde genommen. Wenn es ein Element hinzugefügt werden muss, es fügt sie in das Array, etc. Ich dachte, ich drei Invarianten hatte:Wie frei kann ich im Code in einer Objektinvariante sein?
- Der Graf muss sinnvoll sein: nicht-negativ und höchstens so groß wie die Puffergröße
- Alles in dem ungenutzten Teil des Puffers sollte im Altteil des Puffers sollte mindestens so „groß“ wie das Element sein, bevor es
Jetzt
[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);
}
}
Leider ccrewrite
ist die Schleifen durcheinander.
Die Benutzerdokumentation sagt, dass die Methode sollte nur eine Reihe von Anrufen zu Contract.Invariant
sein. Muss ich den Code wirklich so umschreiben?
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));
Das ist etwas hässlich, obwohl es funktioniert. (Es ist viel besser als mein früherer Versuch, wohlgemerkt.)
Sind meine Erwartungen unvernünftig? Sind meine Invarianten unvernünftig?
(auch gefragt, als question in the Code Contracts forum. Ich alle relevanten Antworten uns hier hinzufügen würde.)
Anscheinend können Sie nicht so frei sein wie die Schleife entrollt./rimshot –
Das Bizarre ist, dass die * erste * Schleife in Ordnung ist ... aber die zweite nicht. Es könnte natürlich ein Fehler in ccrewrite sein. –
(Ich vermute, es ist die Erfassung all den Code vor dem Aufruf von Contract.Invariant ...) –