Ricerca…


Sintassi

  1. Contract.Requires (Condizione, UserMessage)

    Contract.Requires (Condizione, UserMessage)

    Contract.Result <T>

    Contract.Ensures ()

    Contract.Invariants ()

Osservazioni

.NET supporta l'idea Design by Contract tramite la classe Contracts presente nello spazio dei nomi System.Diagnostics e introdotta in .NET 4.0. Code Contracts API include classi per il controllo statico e di runtime del codice e consente di definire precondizioni, postcondizioni e invarianti all'interno di un metodo. Le condizioni preliminari specificano le condizioni che i parametri devono soddisfare prima che un metodo possa essere eseguito, le postcondizioni verificate al completamento di un metodo e le invarianti definiscono le condizioni che non cambiano durante l'esecuzione di un metodo.

Perché sono necessari i Contratti di codice?

Tenere traccia dei problemi di un'applicazione quando la tua applicazione è in esecuzione, è una delle preoccupazioni principali di tutti gli sviluppatori e amministratori. Il monitoraggio può essere eseguito in molti modi. Per esempio -

  • È possibile applicare la traccia sulla nostra applicazione e ottenere i dettagli di un'applicazione quando l'applicazione è in esecuzione

  • È possibile utilizzare il meccanismo di registrazione degli eventi quando si esegue l'applicazione. I messaggi possono essere visualizzati utilizzando il Visualizzatore eventi

  • È possibile applicare il monitoraggio delle prestazioni dopo un intervallo di tempo specifico e scrivere dati in tempo reale dall'applicazione.

I Contratti di codice utilizzano un approccio diverso per il rilevamento e la gestione dei problemi all'interno di un'applicazione. Invece di convalidare tutto ciò che viene restituito da una chiamata di metodo, Contratti di codice con l'aiuto di precondizioni, postcondizioni e invarianti sui metodi, assicurarsi che tutto ciò che entra e che lasci i metodi sia corretto.

presupposti

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

postconditions

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

invarianti

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

Definizione dei contratti sull'interfaccia

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

Nel codice precedente, abbiamo definito un'interfaccia chiamata IValidation con un attributo [ContractClass] . Questo attributo prende un indirizzo di una classe in cui abbiamo implementato un contratto per un'interfaccia. La classe ValidationContract utilizza le proprietà definite nell'interfaccia e verifica i valori null utilizzando Contract.Requires<T> . T è una classe di eccezione.

Abbiamo anche contrassegnato l'accesso get con un attributo [Pure] . L'attributo puro garantisce che il metodo o una proprietà non modifichi lo stato dell'istanza di una classe in cui è implementata l'interfaccia di IValidation .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow