Vra

Ek probeer om te demonstreer invarianten in die Kode Kontrakte, en ek het gedink ek wil gee'n voorbeeld van'n gesorteerde lys van die snare.Dit hou'n verskeidenheid intern, met ekstra ruimte vir aanbouings, ens - net soos List<T>, basies.Wanneer is dit nodig om by te voeg'n item, dit voeg dit in die skikking, ens.Ek het gedink ek het drie invarianten:

  • Die graaf moet sinvol wees:nie-negatiewe en ten minste so groot soos die buffer grootte
  • Alles in die ongebruikte deel van die buffer moet nul wees
  • Elke item in die gebruik deel van die buffer moet ten minste as "groot" as die item voor dit

Nou, ek het probeer om te implementeer wat op hierdie manier:

[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);
    }
}

Ongelukkig, ccrewrite is geknoei die loops.

Die gebruiker dokumentasie sê dat die metode moet net'n reeks van oproepe om Contract.Invariant.Moet ek regtig het om te herskryf die kode soos iets soos hierdie?

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));

Dit is'n bietjie lelik, maar dit werk nie.(Dit is baie beter as my vorige poging, dink jy.)

Is my verwagtinge onredelik?Is my invarianten onredelik?

(Ook gevra om as'n vraag in die Kode Kontrakte forum.Ek sal enige relevante antwoorde hier myself.)

Was dit nuttig?

Oplossing

Van die (voorlopige) MSDN bladsye dit lyk asof die Contract.ForAll lid kan jou help met die 2 reeks kontrakte. Die dokumentasie is nie baie duidelik oor sy funksie al is.

//untested
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));

Ander wenke

(Ek gaan om te aanvaar Henk se antwoord, maar ek dink dit is die moeite werd om die toevoeging van hierdie.)

Die vraag is nou antwoord op die MSDN forum, en die uiteinde is dat die eerste vorm is nie verwag om te werk.Invarianten regtig, regtig nodig het om'n reeks van oproepe om Contract.Invariant, en dit is al.

Dit maak dit meer haalbaar vir die statiese checker om te verstaan die onveranderlike en dit afdwing.

Hierdie beperking kan omseil word deur eenvoudig om al die logika in'n ander lid, bv.'n IsValid eiendom, en dan roep:

Contract.Invariant(IsValid);

Dit sou geen twyfel gemors die statiese checker, maar in sommige gevalle mag dit wees'n nuttige alternatief in sommige gevalle.

Is nie die ontwerpers die wiel weer uitvind 'n bietjie?

Wat was verkeerd met die goeie ou

was
bool Invariant() const; // in C++, mimicking Eiffel

?

Nou in C # wat ons nie const het, maar hoekom kan jy nie net 'n Invariant funksie definieer

private bool Invariant()
{
  // All the logic, function returns true if object is valid i.e. function
  // simply will never return false, in the absence of a bug
}
// Good old invariant in C#, no special attributes, just a function

en dan net gebruik om die Kode Kontrakte ingevolge daardie funksie?

[ContractInvariantMethod]
private void ObjectInvariant()
{
    Contract.Invariant(Invariant() == true);
}

Miskien is ek skryf nonsens, maar selfs in so 'n geval is dit 'n paar didaktiese waarde sal hê wanneer almal vertel my verkeerd verstaan.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top