コード コントラクト

# 事後条件

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> を使用して null 値をチェックします . T は例外クラスです。

また、属性 [Pure] で get アクセサーをマークしました。 .純粋な属性は、メソッドまたはプロパティがクラスのインスタンス状態を変更しないことを保証します IValidation インターフェイスが実装されています。

# 前提条件

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

# 構文

  • Contract.Requires(Condition,userMessage)Contract.Requires(Condition,userMessage)Contract.ResultContract.Ensures()Contract.Invariants()
  • # コメント

    .NET は、System.Diagnostics 名前空間にあり、.NET 4.0 で導入された Contracts クラスを介して、Design by Contract の考え方をサポートしています。 Code Contracts API には、コードの静的およびランタイム チェック用のクラスが含まれており、メソッド内で事前条件、事後条件、および不変条件を定義できます。事前条件は、メソッドが実行される前にパラメーターが満たす必要のある条件、メソッドの完了時に検証される事後条件を指定し、不変条件はメソッドの実行中に変更されない条件を定義します。

    なぜコード コントラクトが必要なのですか?

    アプリケーションの実行中にアプリケーションの問題を追跡することは、すべての開発者と管理者にとって最大の関心事の 1 つです。追跡はさまざまな方法で実行できます。例-

  • アプリケーションにトレースを適用し、アプリケーションの実行中にアプリケーションの詳細を取得できます
  • アプリケーションの実行中に、イベント ロギング メカニズムを使用できます。メッセージは、イベント ビューアーを使用して表示できます
  • 特定の時間間隔の後にパフォーマンス モニタリングを適用し、アプリケーションからライブ データを書き込むことができます。
  • Code Contracts は、アプリケーション内の問題を追跡および管理するために別のアプローチを使用します。メソッド呼び出しから返されるすべてを検証する代わりに、メソッドの事前条件、事後条件、および不変条件を使用してコード コントラクトを使用し、メソッドに出入りするすべてが正しいことを確認します。