現在、独自のコレクションを作成しようとしています。これは、通常のリストのようになりますが、10個のアイテムしか保持できません。リストにすでに10個のアイテムがあるときにアイテムが追加された場合、新しいアイテムが追加される前に最初のアイテムが削除されます。
私がやりたいのは、_System.Collections.Generic.List<T>
_を拡張するクラスを作成し、Add(T item)
メソッドを変更して、必要に応じて最初の項目を削除する機能を含めることです。
まず、Addをオーバーライドできず、 List に対してポリモーフィズムを保持できます。つまり、新しいキーワードを使用し、クラスがリストとしてキャストされた場合、新しいAddメソッドは呼び出されません。
次に、 Queue クラスを調べることをお勧めします。これは、リストよりもキューの方が目的だからです。このクラスは、目的に合わせて最適化されていますが、サイズ制限はありません。
何かをリストのように機能させたいが、最大サイズのキューのように動作させたい場合は、 IList を実装し、キューのインスタンスを保持して要素を保存することをお勧めします。
例えば:
public class LimitedQueue<T> : IList<T>
{
public int MaxSize {get; set;}
private Queue<T> Items = new Queue<T>();
public void Add(T item)
{
Items.Enqueue(item);
if(Items.Count == MaxSize)
{
Items.Dequeue();
}
}
// I'll let you do the rest
}
経由でaddメソッドを実装することもできます
public new void Add(...)
派生クラスで既存の追加を非表示にし、機能を導入します。
編集:ラフアウトライン...
class MyHappyList<T> : List<T>
{
public new void Add(T item)
{
if (Count > 9)
{
Remove(this[0]);
}
base.Add(item);
}
}
暗示されたと考えられますが、カスタムリストは常に実際の型で参照し、ベース型/インターフェイスではなく、非表示メソッドは自分の型およびその他の派生型でのみ使用できるため、参照する必要があります。
Add()をオーバーライドすることはできません。これは仮想メソッドではありません。代わりにIListから派生し、実装にプライベートキューメンバーを使用します。
System.Collections.ObjectModel.Collection を拡張し、InsertItemメソッドをオーバーライドして、必要な動作を取得できます。また、IListも実装します。
内部IList<T>
を保持するList<T>
を実装するクラスを記述し、独自のメソッドを記述することができます。
私ができる最善のことはこれだと思われます:
_class MostRecentList<T> : System.Collections.Generic.List<T> {
private int capacity;
public MostRecentList(int capacity) : base() {
this.capacity = capacity;
}
public new void Add(T item) {
if (base.Count == capacity) {
base.RemoveAt(0);
}
base.Add(item);
}
}
_
add()
メソッドは仮想としてマークされていないため。
要件の説明は 循環バッファー のように聞こえます。
私は自分で実装しました- CodePlexでのこの実装 に似ていますが、私の実装はIList<T>
を実装しています。
他の答えのいくつかは、Queue<T>
の使用を提案していますが、これはFIFOアクセスのみを許可するため、まったく同じものではありません。
一般的なポイントとして、List<T>
から派生することはお勧めできません-代わりにCollection<T>
から派生し、必要な追加のものを実装してください。ただし、循環バッファーの場合は、おそらくCodePlex実装のようにCollection<T>
から派生するのではなく、プライベート配列を使用する方が適切です。
Liskov Substitution Principle を読んでください。あなたのコレクションはList<T>
を拡張するのに非常に貧弱な候補であり、IList<T>
を実装するための素晴らしい候補ではありません。
このデータにはどのような読み取りパターンが必要ですか?現在のすべてのエントリのみを見る必要がある場合は、IEnumerable<T>
とAdd(T)メソッドを実装するだけで十分です。
これはプライベートキューによって実装できます(またはDequeの方が優れていますが、そのようなコレクションには他のコレクションAPIが必要であり、自分で実装することはお勧めしません)。サイズを維持するために必要)。
IEnumerableを実装し、Addメソッドを提供することは、必要に応じてコレクション初期化構文を引き続き使用できることを意味します。
値へのランダムアクセスが必要な場合は、インデクサーを実装することをお勧めしますが、質問のコンテキストがなければ、これがどのようなメリットをもたらすかはわかりません。
C5コレクションライブラリをご覧ください。 IList <T>を実装するArrayList <T>があり、仮想のAddメソッドがあります。 C5コレクションライブラリは、リスト、キュー、スタックなどの素晴らしいコレクションです。C5ライブラリは次の場所にあります。
System.Collections.ObjectModel.Collection<T>
の拡張を試みることができます。これは、はるかに柔軟です。その後、保護されたメンバーInsertItem
およびSetItem
をオーバーライドして、コレクションの動作をカスタマイズできます。