4

誰かがC#でStackクラスを実装する方法/最良の方法についての例やアイデアを持っていますか?すでにStackクラスがあることは理解していますが、実際にStackクラスを実装する方法を理解する必要があります。

また、C#でコントラクトを使用して、このクラスの前提条件、事後条件、および不変条件を指定する方法についてのアドバイスも必要です。ASP.NET MVCアーキテクチャでモデルを作成するときに、以前に似たようなものを使用したことがあると思いますが、それが同じものであり、同じように機能するかどうかは完全にはわかりません。(前提条件/事後条件/不変条件については、まだわからない場合は少し迷っています。ご容赦ください。)

私の主な質問-スタックなどのクラスでコントラクトを適切に使用するためのアドバイスを誰かに教えてもらえますか?

はい、私は努力を打ち出しました:

public interface IStack
{
        void Push(Object e);
        Object Pop();
        Object Top();
        void EnsureCapacity();
    }
}

   public class Stack : IStack
{
    private Object[] elements;
    private int size = 0;

    public Stack()
    {
        elements = new Object[0];
    }

    public void Push(Object e)
    {
        // check if this array capacity has been reached and increase if needed
        EnsureCapacity();
        elements[size++] = e;
    }

    public Object Pop()
    {
        // check if the method call is invalid for the object's current state
        if (size == 0) throw new InvalidOperationException("Stack.Pop");

        Object result = elements[--size];
        elements[size] = null;

        return result;
    }

    public Object Top()
    {
        // check if the method call is invalid for the object's current state
        if (size == 0) throw new InvalidOperationException("Stack.top");
        return elements[(size - 1)];
    }

    private void EnsureCapacity()
    {
        if (elements.Length == size)
        {
            Object[] oldElements = elements;
            elements = new Object[(2 * size + 1)];
        }
    }
}
4

2 に答える 2

1

c#で実装されているコレクションの多くは、配列に基づいています。配列を使用して最後に要素を追加し、最上位の要素のインデックスを保持して、新しい要素がプッシュされている間それを増やすことができます。もちろん、新しいオブジェクトが表示され、現在のアレイにはそれらの場所はありません。

コードコントラクトには、 http://research.microsoft.com/en-us/projects/contracts/userdoc.pdfで入手できるかなり優れたドキュメントがあります。

于 2011-10-05T22:03:13.387 に答える
1

必要に応じて、Microsoft Code Contracts の使用を開始するために、一度ブログに投稿しました。その投稿では、前提条件、事後条件、および不変条件の非常に基本的な内容について説明しています。

概念の要約として、次のように考えることができます。

  • 前提条件とは、メソッドが実行される前に真でなければならないもの、つまりクライアントがメソッドに約束するものです。
  • 不変は、クラスのクライアントに関する限り、常に公的に真実であり続けなければならないものです。
  • 事後条件は、メソッドの実行後に真でなければならないもの、つまりメソッドがクライアントに約束するものです。

ですから、頭のてっぺんから、スタックの場合、考えやすいのは不変条件かもしれません。配列を使用してスタックをモデル化している場合は、配列が null に設定されないという不変条件をクラスで宣言できます。たとえば、不変条件メソッドを定義します。

[ContractInvariantMethod]
private void ObjectInvariant()
{
   Contract.Invariant(elements != null);
}   

pop メソッドには既に前提条件があるようです。ユーザーが pop を実行するときにスタックが空でないことを確認するのはユーザーの義務であると言いたいのです。したがって、pop メソッドの先頭では、次のようになります。

Contract.Requires(size > 0);

最後に、pop の事後条件を指定すると、そのサイズは pop 操作前よりも常に小さくなります (必要に応じて、より具体的にすることもできます)。

Contract.Ensures(Contract.OldValue<int>(size) > size);

頑張ってください -- コントラクトはクールで便利です。これは非常にクリーンなコーディング方法です。

于 2011-10-05T22:57:34.353 に答える