Szukaj…


Składnia

  1. Contract.Requires (Condition, userMessage)

    Contract.Requires (Condition, userMessage)

    Contract.Result <T>

    Contract.Ensures ()

    Contract.Invariants ()

Uwagi

.NET obsługuje ideę Design by Contract poprzez klasę Contracts znajdującą się w przestrzeni nazw System.Diagnostics i wprowadzoną w .NET 4.0. Interfejs API kontraktów kodowych obejmuje klasy do sprawdzania statycznego i wykonawczego kodu i pozwala definiować warunki wstępne, dodatkowe i niezmienne w ramach metody. Warunki wstępne określają warunki, które parametry muszą spełnić, aby metoda mogła zostać wykonana, warunki dodatkowe, które są weryfikowane po zakończeniu metody, a niezmienniki określają warunki, które nie zmieniają się podczas wykonywania metody.

Dlaczego potrzebne są umowy kodowe?

Śledzenie problemów z aplikacją podczas jej działania jest jednym z głównych problemów wszystkich programistów i administratorów. Śledzenie można wykonać na wiele sposobów. Na przykład -

  • Możesz zastosować śledzenie w naszej aplikacji i uzyskać szczegółowe informacje o aplikacji, gdy aplikacja jest uruchomiona

  • Podczas uruchamiania aplikacji można użyć mechanizmu rejestrowania zdarzeń. Wiadomości można zobaczyć za pomocą Podglądu zdarzeń

  • Możesz zastosować monitorowanie wydajności po określonym czasie i zapisać dane na żywo z aplikacji.

Code Contracts stosuje inne podejście do śledzenia problemów w aplikacji i zarządzania nimi. Zamiast sprawdzania poprawności wszystkiego, co jest zwracane z wywołania metody, kodowanie kontraktów za pomocą warunków wstępnych, warunków dodatkowych i niezmienników metod zapewnia, że wszystko, co wchodzi i wychodzi z metod, jest poprawne.

Warunki wstępne

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

Warunki dodatkowe

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

Niezmienniki

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

Definiowanie umów dotyczących interfejsu

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

W powyższym kodzie zdefiniowaliśmy interfejs o nazwie IValidation z atrybutem [ContractClass] . Ten atrybut przyjmuje adres klasy, w której wdrożyliśmy umowę dotyczącą interfejsu. Klasa ValidationContract wykorzystuje właściwości zdefiniowane w interfejsie i sprawdza wartości zerowe za pomocą Contract.Requires<T> . T to klasa wyjątków.

Oznaczyliśmy również get accessor atrybutem [Pure] . Czysty atrybut zapewnia, że metoda lub właściwość nie zmieni stanu instancji klasy, w której IValidation jest interfejs IValidation .



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow