Поиск…


Синтаксис

  1. Contract.Requires (условие, userMessage)

    Contract.Requires (условие, userMessage)

    Contract.Result <Т>

    Contract.Ensures ()

    Contract.Invariants ()

замечания

.NET поддерживает идею Design by Contract через свой класс Contracts, найденный в пространстве имен System.Diagnostics и представленный в .NET 4.0. API Code Contracts API включает в себя классы для проверки статичности и времени выполнения кода и позволяет определять предварительные условия, постусловия и инварианты внутри метода. Предварительные условия определяют условия, которые должны выполнять параметры перед тем, как метод может выполнить, постусловия, которые проверяются по завершении метода, а инварианты определяют условия, которые не изменяются во время выполнения метода.

Зачем нужны кодовые контракты?

Отслеживание проблем приложения, когда приложение работает, является одной из главных проблем всех разработчиков и администраторов. Отслеживание может выполняться многими способами. Например -

  • Вы можете применить трассировку в нашем приложении и получить информацию о приложении, когда приложение запущено

  • Вы можете использовать механизм регистрации событий при запуске приложения. Сообщения можно увидеть с помощью средства просмотра событий

  • Вы можете применять мониторинг производительности через определенный промежуток времени и записывать данные в реальном времени из своего приложения.

Кодовые контракты используют другой подход для отслеживания и управления проблемами в приложении. Вместо того, чтобы проверять все, что возвращается из вызова метода, Кодовые контракты с помощью предварительных условий, постусловий и инвариантов в методах, убедитесь, что все входящие и выходящие из ваших методов правильны.

Предпосылками

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

Постусловия

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

Инварианты

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

Определение контрактов по интерфейсу

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

В приведенном выше коде мы определили интерфейс под названием IValidation с атрибутом [ContractClass] . Этот атрибут принимает адрес класса, в котором мы реализовали контракт для интерфейса. Класс ValidationContract использует свойства, определенные в интерфейсе, и проверяет нулевые значения с использованием Contract.Requires<T> . T - класс исключения.

Мы также отметили get accessor с атрибутом [Pure] . Чистый атрибут гарантирует, что метод или свойство не изменяет состояние экземпляра класса, в котором IValidation интерфейс IValidation .



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow