Próbuję zademonstrować niezmienniki w Code Contracts i pomyślałem, że podam przykład posortowanej listy ciągów znaków. Utrzymuje tablicę wewnętrznie, z dodatkową przestrzenią dla dodatków itp. - tak jak w zasadzie List<T>
. Kiedy trzeba dodać element, to wstawia go do tablicy, itd. Pomyślałem, miałem trzy niezmienników:Jak wolny mogę być w kodzie w niezmienniku obiektu?
- Ilość musi być rozsądne: nieujemne i co najwyżej tak duży jak rozmiar bufora
- Wszystko w niewykorzystanej części bufora powinna być zerowa
- Każda pozycja w używane części bufora powinna wynosić co najmniej jako „duży” jako elementu przed
teraz Próbowałam wdrożyć w ten sposób:
[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);
}
}
Niestety, ccrewrite
psuje pętle.
Dokumentacja użytkownika mówi, że metoda powinna być po prostu serią połączeń z numerem Contract.Invariant
. Czy naprawdę muszę przepisać kod jako coś takiego?
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));
To trochę brzydkie, chociaż działa. (To znacznie lepsze niż moja poprzednia próba, pamiętajcie.)
Czy moje oczekiwania są nieuzasadnione? Czy moje niezmienniki są nierozsądne?
(poprosił także jako question in the Code Contracts forum. Dodam żadnych stosownych odpowiedzi tutaj sam.)
Wygląda na to, że nie możesz być tak wolny, jak pętla się rozwija./rimshot –
Dziwne jest to, że * pierwsza * pętla jest w porządku ... ale druga nie jest. Oczywiście może to być błąd w ccrewrite. –
(Podejrzewam, że przechwytuje cały kod przed wywołaniem umowy. Wariant ...) –