2015-03-18 13 views
9

Ich habe ein Problem bei der Verwendung von Invarianten mit Code-Verträgen festgestellt. Ich möchte eine Invariante innerhalb meiner abstrakten Klasse definieren, aber sie wird einfach ignoriert. Der folgende Code zeigt meine Schnittstelle und die abstrakte Klasse.Code Contracts: Invarianten in abstrakte Klasse

[ContractClass(typeof(IPointContract))] 
interface IPoint 
{ 
    int X { get; } 
    int Y { get; } 
} 

[ContractClassFor(typeof(IPoint))] 
abstract class IPointContract : IPoint 
{ 

    public int X 
    { 
     get { return 0; } 

    } 

    public int Y 
    { 
     get { return 0; } 
    } 

    [ContractInvariantMethod] 
    private void PointInvariant() 
    { 
     Contract.Invariant(X > Y); 
    } 
} 

Danach implementiere ich diese Schnittstelle innerhalb meiner Point-Klasse und erstelle ein Objekt daraus. Dies sollte zumindest während der Laufzeit fehlschlagen.

class Point : IPoint 
{ 
    public Point(int X, int Y) 
    { 
     this._x = X; 
     this._y = Y; 
    } 

    private int _x; 
    public int X 
    { 
     get { return _x; } 
    } 

    private int _y; 
    public int Y 
    { 
     get { return _y; } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Point p = new Point(1, 2); 
    } 
} 

Als ich die unveränderliche auf den Punkt-Klasse bewegen, es funktioniert gut. Alle anderen Vor- oder Nachbedingungen funktionieren auch gut.

Ist es nicht möglich, Invarianten innerhalb einer abstrakten Klasse zu haben, oder mache ich es falsch?

+0

Warum benennen Sie eine abstrakte Klasse mit Interface-Semantik? Eine abstrakte Klasse ist keine Schnittstelle und sollte nicht mit I beginnen. –

+0

Ich verwende die gleiche Semantik wie im Code-Vertragshandbuch. Siehe Kapitel 2.8 http://research.microsoft.com/en-us/projects/contracts/userdoc.pdf – Dynamike

+1

Ich sehe ... Es ist nicht I-FooContract, es ist IFoo-Contract. Wenn ich es wäre, würde ich es wahrscheinlich ContractForIFoo schreiben, um klar zu sein, aber vielleicht gibt es hier eine Konvention ... –

Antwort

2

Invarianten werden nicht an Schnittstellen unterstützt. (Der Titel Ihrer Frage lautet "Invariants in abstract class", aber der Kern des Problems liegt in der Schnittstelle.)

Meine Vermutung ist, dass Invarianten State benötigen, aber Schnittstellen keinen Status haben. Ich bin mir sicher, dass das Code-Contract-Team das umgehen kann und ich wünschte, sie würden es tun, weil dies ein großartiges Feature wäre.

, um diese Einschränkung zu umgehen können Sie:

  • die invariante Methode zu den abgeleiteten Klassen hinzufügen (class Point, etc.).
  • Oder fügen Sie den abstrakten Klasseneigenschaften Setter hinzu und implementieren Sie die Vertragslogik in den Setter.