この記事は機械翻訳されたものです。

働くプログラマ

.NET コレクション、第 2 部: C5 を扱う (機械翻訳)

Ted Neward

 

 

Ted Neward再びようこそ。

このシリーズの最初の部分、コペンハーゲンの包括的なコレクション クラスの c# (C5) ライブラリを簡単に見て、一連の補完 (ではないを置き換える)、System.Collections 設計クラス クラスを Microsoft .NET Framework のランタイム ライブラリと船。 部分的 C5 は、.NET Framework クラス ライブラリ (FCL) を使用して、同じ手法の多くをフォローしたいので 2 つのライブラリ間の重複のかなりの量が、理由があるのでだけそう多くの方法 1 つは、合理的に特定のコレクション型を表すことができます。 (インデックス付きコレクションを想像するは難しい-辞書やリストなど — インデックス付きプロパティの言語構文をサポートしていません。c# および Visual Basic で「()」演算子の""演算子などです。)FCL コレクションは実用的です、ただし、C5 コレクション、ステップまたは 2 つ以外にも、行く、それが我々 の時間を過ごすしたいです。

(注があることも非常に可能性が高いいくつかのパフォーマンス違い 2 つのライブラリとその支持者またはそれぞれの評論家が指摘する — C5 コレクション マニュアル パフォーマンスへの影響のいくつかの例について説明します。 一般に、1 つの特定のケースまたはケースのセットには、誰かが本当には、2 つの間のすべての場合は true を保持するかどうか言っていません、他よりも高速に実行する 2 つの 1 つを得たということですすべてのベンチマークを証明しているという理由で、ほとんどのパフォーマンスのベンチマークを使わないようにと述べた。 全てのベンチマークは、役に立たない、ちょうどコンテキストをベンチマークが重要であるわけではありません。 読者は、特定のシナリオを取る、それらにベンチマークを無効に、だけこれら特定のケースでの顕著な違いがあるかどうかを参照する、2 つの間の銃撃戦は強く奨励されます。)

実装

まず第一に、C5 を提供しています別のコレクションの実装で簡単に見てみましょう。 再び、我々 は最後の時間を説明したように、C5 を使用する開発者が一般的に作成する実装を決定する場合を除いて使用の実装について心配しないでください-インターフェイス型では、コレクションの残りの部分を参照する必要があります。 (インターフェイス型の説明についてを参照してください以前のコラムで、シリーズで msdn.microsoft.com/magazine/jj883961、または C5 のドキュメントで bit.ly/UcOcZH.)実装を次に示します。

  • CircularQueue <T> 両方の i キュー <T> を実装します。 IStack <T> i キュー <T> の先入れ先出しセマンティクスを提供するには (経由 Enqueue と Dequeue) または IStack <T> の先入れ先出しセマンティクス (プッシュとポップを介して) リンクされたリストをバックアップしました。 必要に応じての能力を成長します。
  • ArrayList <T> IList <T> IStack <T> を実装します。 i <T> キュー バックアップ配列で。
  • LinkedList <T> IList <T> IStack <T> を実装します。 i <T> キュー ノードの二重にリンクされたリストを使用します。
  • HashedArrayList <T> IList <T> 配列では、バックアップを実装がまた内部で効率的に、リスト内の項目の位置を検索するには、ハッシュ テーブルを維持します。 また、それ (重複ハッシュ テーブル ルックアップを台無しにするので) リストに重複は許可されません。
  • HashedLinkedList <T> <T>、IList を実装するバックアップ リンクのリストで、配列バックアップいとこのように、内部ハッシュ テーブル ルックアップを最適化するために使用します。
  • WrappedArray <T> 1 次元の配列の周りをラップ IList <T> を実装します。 このクラスの利点は、単に「それをはるかに高速、配列と ArrayList <T> に要素をコピーではなく、C5 機能を取得すること、配列飾ること」です。
  • SortedArray <T> コレクションすることができますされるインデックスし同様に並べ替えを意味する IIndexedSorted <T> を実装する-私たちはこの 2 番目を取得します。 それは、並べ替えの項目を保持し、重複を許可しません。
  • TreeSet <T> IIndexedSorted <T> を実装します。 IPersistedSorted <T> 挿入、削除、および並べ替えのために大きい、バランスの取れたレッド ブラック ツリーによって支えられています。 すべてのセットのような重複を許可しません。
  • TreeBag <T> IIndexedSorted <T> を実装します。 IPersistedSorted <T> は、バランスの取れたレッド ブラック ツリーによって支えられて、重複できます「本質的には (時々「マルチセット」と呼ばれる) バッグ」を意味します。
  • HashSet <T> IExtensible <T> を実装し、(意味の重複) セット線形の組み合わせをハッシュ テーブルでバックアップします。 つまり検索される高速、変更少ないので。
  • HashBag <T> IExtensible <T> を実装し、(重複を許可を意味) バッグ線形チェーンとハッシュ テーブルがバックアップ再び高速検索を行います。
  • IntervalHeap <T> 「最大値」または"min"優先順位キューの末尾からプルする効率的な作りのペアの配列として格納間隔ヒープを使用して IPriorityQueue <T> を実装します。

いくつかのより多くの実装があり、興味があるなら、C5 マニュアルとドキュメントの詳細があります。 インスタンスを 1 つを選択するときは、それぞれの良いアイデアを持つことができますので、ただし、パフォーマンスへの影響から、重要なことは知っているどのインターフェイスを実装です。 (常にそれを回避する別の実装後に、常に、その実装型ではなく、インターフェイスのコレクションを参照するには、C5 のデザイン ガイドラインに従うと仮定すると切り替えすることができます。)

機能

C5 コレクションの実装の大規模なコレクションだけなら、それは興味深い、しかし、おそらく十分な重要な関心やディスカッションを保証するでしょう。 幸いなことに、それの議論に値する開発者にいくつかの新しい機能を提供します。

ビュー の興味深い一口 C5 ライブラリの 1 つは「ビュー」の概念。サブコレクションは、実際には、コピーではありませんが、元のコレクションによってバックアップ ソース コレクションの要素の。 これは実際に前の列からコード、調査テストでしたものでした。 参照してください図 1 コレクションのビューを作成する方法について。

図 1 コレクションのビューを作成します。

[TestMethod]
public void GettingStarted()
{
  IList<String> names = new ArrayList<String>();
  names.AddAll(new String[]
    { "Hoover", "Roosevelt", "Truman", "Eisenhower", "Kennedy" });
  // Print item 1 ("Roosevelt") in the list
  Assert.AreEqual("Roosevelt", names[1]);
  Console.WriteLine(names[1]);
  // Create a list view comprising post-WW2 presidents
  IList<String> postWWII = names.View(2, 3);
  // Print item 2 ("Kennedy") in the view
  Assert.AreEqual("Kennedy", postWWII[2]);
}

ビューは、何らかの理由で、元のリストを変更した場合、ビューにも適用されます、元のリストによって支えられています。 参照してください図 2 回した可能性のある変更を確認します。

図 2 ビューは潜在的に不変であります。

[TestMethod]
public void ViewExploration()
{
  IList<String> names = new ArrayList<String>();
  names.AddAll(new String[]
    { "Washington", "Adams", "Jefferson",
      "Hoover", "Roosevelt", "Truman",
      "Eisenhower", "Kennedy" });
  IList<String> postWWII = names.View(4, names.Count - 4);
  Assert.AreEqual(postWWII.Count, 4);
  IList<String> preWWII = names.View(0, 5);
  Assert.AreEqual(preWWII.Count, 5);
  Assert.AreEqual("Washington", preWWII[0]);
  names.Insert(3, "Jackson");
  Assert.AreEqual("Jackson", names[3]);
  Assert.AreEqual("Jackson", preWWII[3]);
}

このテストを示すように、基になるリスト (「名前」) を変更する今、ビューの最初の要素「ワシントン」は (この場合は"preWWII"ビュー) に定義されたビューもその内容を変更する、「ではなくフーバー」見つけることを示します

ただし、可能であれば、C5 ビューの尊厳を維持する; (ここで C5、"preWWII"ビューの内容を変更することがなく挿入できます)、コレクションの前に挿入が発生した場合は、ので、たとえば、[ビューの内容変更されません。

[TestMethod]
public void ViewUnchangingExploration()
{
  IList<String> names = new ArrayList<String>();
  names.AddAll(new String[]
    { "Hoover", "Roosevelt", "Truman", "Eisenhower", "Kennedy" });
  IList<String> preWWII = names.View(0, 2);
  Assert.AreEqual(preWWII.Count, 2);
  names.InsertFirst("Jackson");
  Assert.AreEqual("Jackson", names[0]);
  Assert.AreEqual("Hoover", preWWII[0]);
}

その他 (杭) 不変コレクション主不変オブジェクトについての理由を理解し、やすく多くの開発者を見つけるので不変オブジェクトで多くの利点に対して-à-に対して同時実行と並列プログラミングも提供していますので関数型の概念とプログラミング スタイルの上昇によって、多くの重点に不変データおよび不変のオブジェクトに振ったしています。 その概念は、当然の結果の後、次のように不変のコレクションの概念-コレクション内のオブジェクト変更できないかどうかに関係なく、コレクション自体固定と変更することはできませんがアイデア (追加または削除) コレクション内の要素。 (メモ :NuGet で MSDN 基本クラス ライブラリ (BCL) のブログで公開その他不変のコレクションのプレビューを参照してくださいすることができます bit.ly/12AXD78.)

C5 内不変のコレクションは、関心のあるデータを含むコレクション中の「ラッパー」のコレクションをインスタンス化して処理されます。 これらのコレクションは、「保護された」のコレクションであり、古典的なデコレータ パターン スタイルに使用されます。

public void ViewImmutableExploration()
{
  IList<String> names = new ArrayList<String>();
  names.AddAll(new String[]
    { "Hoover", "Roosevelt", "Truman", "Eisenhower", "Kennedy" });
  names = new GuardedList<String>(names);
  IList<String> preWWII = names.View(0, 2);
  Assert.AreEqual("Hoover", preWWII[0]);
  names.InsertFirst("Washington");
  Assert.AreEqual("Washington", names[0]);
}

だれが追加またはリストから要素を削除するコードを記述しようとする場合は、C5 はすぐに言った開発者のアイデアの disabuses:(追加、挿入、InsertFirst など) の「変更」の方法のいずれかを呼び出すと、例外がスローされます。

これは、方法によって、非常に強力な機会を提供しています。 前回のコラムでは、C5 に行った主要な設計ポイントのいずれかのコレクションをのみインターフェイスを通じて使用する必要がありますアイデアは言及しました。 考え前方デザイン C5 を運ぶを使用すると仮定すると開発者、今渡されますメソッドによってコレクションが決して変更されないようにするは本当に簡単になります (を参照してください図 3)。

図 3 (不変の) その他のコレクションを守られて

public void IWannaBePresidentToo(IList<String> presidents)
{
  presidents.Add("Neward");
}
[TestMethod]
public void NeverModifiedCollection()
{
  IList<String> names = new ArrayList<String>();
  names.AddAll(new String[]
    { "Hoover", "Roosevelt", "Truman","Eisenhower", "Kennedy" });
  try
  {
    IWannaBePresidentToo(new GuardedList<String>(names));
  }
  catch (Exception x)
  {
    // This is expected!
Should be a ReadOnlyException
  }
  Assert.IsFalse(names.Contains("Neward"));
 }

また、渡される IWannaBePresidentToo メソッドがコレクションを変更しようとしたとき (これは、間違いなく、それを書いたのプログラマ側の悪いデザインですが、残念なことには多くのようなコードがある)、例外がスローされます。

ところで、好むべきであるコレクションは例外をスローせず代わりに (はあまりにも微妙だと思うが、いくつかの開発者はその機能必要があります) 修正失敗、杭の独自のバージョンをまとめるは比較的簡単です­アレイ <T> スローしません。

イベント時に、その他のコレクションへの変更は、許可する実際には、— は、コレクションが変更されたときを知りたいだけ。 確かに、あなたがスピン、スレッドをそれコレクションをいつまでもスピンを以前のイテレーションのコンテンツ、内容を比較するがのみこの CPU リソースの恐ろしい物ですが、それを書くし、それはおそらく最悪の可能な設計ソリューションを維持する痛みです- と確かに視力の単にイベントをネイティブにサポート コレクションを使用するよりも貧しい。 C5 のすべてのコレクション、コレクションに対して特定の操作を実行するときに呼び出されるデリゲート コレクションをオフにハングアップする機能を提供 (を参照してください図 4)。

図 4 時、"私は大統領になる..."

[TestMethod]
public void InaugurationDay()
{
  IList<String> names = new ArrayList<String>();
  names.AddAll(new String[]
    { "Hoover", "Roosevelt", "Truman", "Eisenhower", "Kennedy" });
  names.ItemsAdded +=
    delegate (Object c, ItemCountEventArgs<string> args)
  {
    testContextInstance.WriteLine(
      "Happy Inauguration Day, {0}!", args.Item);
  };
  names.Add("Neward");
  Assert.IsTrue(names.Contains("Neward"));
}

もちろん、イベント ハンドラーは、ラムダ式として記述することができます。 それはちょうどもう少しわかりやすい実際の引数の種類を表示するためです。 最初の引数です-キヤノンで — コレクション自体。

NuGet するだけ

C5 の一部 .NET FCL (脇から、FCL がサポートしているが、本当に強く、それは次のように見えることを支持していないインターフェイスを重視)、周り構築ことができませんでしたがこれは、これはテストされて、それだけ、NuGet「インストール パッケージ」離れてです C5 についての素晴らしい事であります。

コーディングを楽しんでください。

Ted Neward* のプリンシパルである & アソシエイツ LLC。彼は 100 以上の記事を書いて、執筆し、など、たくさんの書籍を執筆「プロ F c# 2.0"(Wrox、2010年).彼は、F c# MVP と Java を指摘する専門家、です、Java と .NET の両方の会議、世界中で話します。彼は定期的にコンサルティングを行い、開発者を指導しています。彼の連絡先は ted@tedneward.com (英語のみ) です。また、彼がチームの作業に加わることに興味がある場合の連絡先は、 Ted.Neward@neudesic.com (英語のみ) です。彼のブログは blogs.tedneward.com (英語) で、Twitter は twitter.com/tedneward (英語) でフォローすることができます。*

この記事のレビュー、次技術専門家のおかげで: Immo Landwerth