C# Language
Code-Verträge
Suche…
Syntax
Vertrag.Anforderungen (Bedingung, Benutzermeldung)
Vertrag.Anforderungen (Bedingung, Benutzermeldung)
Vertrag.Ergebnis <T>
Contract.Ensures ()
Vertragsvarianten ()
Bemerkungen
.NET unterstützt die Idee von Design by Contract über die Klasse Contracts, die im Namespace System.Diagnostics gefunden und in .NET 4.0 eingeführt wurde. Die Code Contracts-API enthält Klassen für statische und Laufzeitüberprüfungen von Code und ermöglicht Ihnen das Definieren von Vorbedingungen, Nachbedingungen und Invarianten innerhalb einer Methode. Die Vorbedingungen legen die Bedingungen fest, die die Parameter erfüllen müssen, bevor eine Methode ausgeführt werden kann, Nachbedingungen, die nach Abschluss einer Methode überprüft werden, und die Invarianten definieren die Bedingungen, die sich während der Ausführung einer Methode nicht ändern.
Warum werden Code-Verträge benötigt?
Das Nachverfolgen von Problemen einer Anwendung bei laufender Anwendung ist eines der Hauptanliegen aller Entwickler und Administratoren. Das Tracking kann auf verschiedene Arten durchgeführt werden. Zum Beispiel -
Sie können die Ablaufverfolgung für unsere Anwendung anwenden und die Details einer Anwendung abrufen, wenn die Anwendung ausgeführt wird
Sie können den Ereignisprotokollierungsmechanismus verwenden, wenn Sie die Anwendung ausführen. Die Meldungen können mit der Ereignisanzeige eingesehen werden
Sie können die Leistungsüberwachung nach einem bestimmten Zeitintervall anwenden und Live-Daten aus Ihrer Anwendung schreiben.
Code Contracts verwendet einen anderen Ansatz zum Verfolgen und Verwalten von Problemen in einer Anwendung. Anstatt alles, was von einem Methodenaufruf zurückgegeben wird, zu überprüfen, stellen Code Contracts mithilfe von Vorbedingungen, Nachbedingungen und Invarianten für Methoden sicher, dass alles, was in Ihre Methoden eingeht und diese verlassen, korrekt ist.
Voraussetzungen
namespace CodeContractsDemo
{
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
public class PaymentProcessor
{
private List<Payment> _payments = new List<Payment>();
public void Add(Payment payment)
{
Contract.Requires(payment != null);
Contract.Requires(!string.IsNullOrEmpty(payment.Name));
Contract.Requires(payment.Date <= DateTime.Now);
Contract.Requires(payment.Amount > 0);
this._payments.Add(payment);
}
}
}
Nachbedingungen
public double GetPaymentsTotal(string name)
{
Contract.Ensures(Contract.Result<double>() >= 0);
double total = 0.0;
foreach (var payment in this._payments) {
if (string.Equals(payment.Name, name)) {
total += payment.Amount;
}
}
return total;
}
Invarianten
namespace CodeContractsDemo
{
using System;
using System.Diagnostics.Contracts;
public class Point
{
public int X { get; set; }
public int Y { get; set; }
public Point()
{
}
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
public void Set(int x, int y)
{
this.X = x;
this.Y = y;
}
public void Test(int x, int y)
{
for (int dx = -x; dx <= x; dx++) {
this.X = dx;
Console.WriteLine("Current X = {0}", this.X);
}
for (int dy = -y; dy <= y; dy++) {
this.Y = dy;
Console.WriteLine("Current Y = {0}", this.Y);
}
Console.WriteLine("X = {0}", this.X);
Console.WriteLine("Y = {0}", this.Y);
}
[ContractInvariantMethod]
private void ValidateCoordinates()
{
Contract.Invariant(this.X >= 0);
Contract.Invariant(this.Y >= 0);
}
}
}
Verträge auf der Schnittstelle definieren
[ContractClass(typeof(ValidationContract))]
interface IValidation
{
string CustomerID{get;set;}
string Password{get;set;}
}
[ContractClassFor(typeof(IValidation))]
sealed class ValidationContract:IValidation
{
string IValidation.CustomerID
{
[Pure]
get
{
return Contract.Result<string>();
}
set
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(value), "Customer ID cannot be null!!");
}
}
string IValidation.Password
{
[Pure]
get
{
return Contract.Result<string>();
}
set
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(value), "Password cannot be null!!");
}
}
}
class Validation:IValidation
{
public string GetCustomerPassword(string customerID)
{
Contract.Requires(!string.IsNullOrEmpty(customerID),"Customer ID cannot be Null");
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(customerID), "Exception!!");
Contract.Ensures(Contract.Result<string>() != null);
string password="AAA@1234";
if (customerID!=null)
{
return password;
}
else
{
return null;
}
}
private string m_custID, m_PWD;
public string CustomerID
{
get
{
return m_custID;
}
set
{
m_custID = value;
}
}
public string Password
{
get
{
return m_PWD;
}
set
{
m_PWD = value;
}
}
}
Im obigen Code haben wir eine Schnittstelle namens IValidation
mit einem Attribut [ContractClass]
. Dieses Attribut nimmt die Adresse einer Klasse an, in der wir einen Vertrag für eine Schnittstelle implementiert haben. Die Klasse ValidationContract
verwendet Eigenschaften, die in der Schnittstelle definiert sind, und prüft mithilfe von Contract.Requires<T>
auf die Nullwerte. T
ist eine Ausnahmeklasse.
Wir haben auch den get-Accessor mit einem Attribut [Pure]
. Das pure-Attribut stellt sicher, dass die Methode oder eine Eigenschaft den IValidation
einer Klasse, in der die IValidation
Schnittstelle implementiert ist, nicht ändert.