1

Ich spiele mit den CodeContracts von Microsoft herum und stieß auf ein Problem, das ich nicht lösen konnte. Ich habe eine Klasse mit zwei Konstruktoren:CodeContracts: Wie erfülle ich Require in Ctor mit diesem() Anruf?

Das Beispiel ist vereinfacht. Ich weiß nicht, wie man die f des zweiten Konstruktors als> 0 überprüfen kann. Ist das sogar mit Contracts möglich?

+0

warum möchten Sie das? das aufrufend ((float) i) prüft bereits auf f> 0 – chiccodoro

Antwort

2

Sie können die Vorbedingung einfach dem Körper des zweiten Konstruktors hinzufügen.

public TestClass(float f) 
{ 
    Contract.Requires(f > 0); 
    throw new Exception("foo"); 
} 
public TestClass(int i): this((float)i) 
{ 
    Contract.Requires(i > 0); 
} 

EDIT

Versuchen Sie den Code oben mit Aufruf:

TestClass test2 = new TestClass((int)-1); 

Sie werden sehen, dass die Voraussetzung ausgegeben, bevor der reguläre Ausnahme ausgelöst.

+0

Ich vermute, dass die hinzugefügte Zeile erst ausgewertet wird, nachdem der float-Konstruktor bereits aufgerufen wurde, oder? – chiccodoro

+1

@Chiccodoro: Eigentlich nein. Ich habe es getestet, um sicher zu sein, und wenn Sie eine throw -Ausnahme in den ersten Konstruktor Körper setzen und den zweiten Konstruktor mit ungültiger Eingabe aufrufen würde Code Contracts eine Präkondition gescheitert werfen ("i> 0"), bevor es die werfen würde Ausnahme vom ersten Konstruktor. – koenmetsu

+0

Ist also "Vertrag" eine Sprachenerweiterung und keine Bibliothek? Weil normalerweise der Basisklassenkonstruktor * vor * dem Unterklassenkonstruktor ausgeführt wird. – chiccodoro

1

Ich würde eine statische Methode hinzufügen, die das Int in den Float konvertiert und die Contract.Requires in dort enthält.

class Foo 
{ 
    public Foo(float f) 
    { 
     Contract.Requires(f > 0); 
    } 
    public Foo(int i) 
     : this(ToFloat(i)) 
    { } 

    private static float ToFloat(int i) 
    { 
     Contract.Requires(i > 0); 
     return i; 
    } 
} 

Hoffe das hilft.