2009-09-09 16 views
27

Dictionary.Clearnew Dictionary()の主な違いは何ですか?どちらのケースにお勧めですか?Dictionary.Clearとnew Dictionary()の相違点

+0

パフォーマンス関連:[より高速なコレクションの収集またはインスタンス化の新機能](http://stackoverflow.com/questions/10901020/which-is-faster-clear-collection-or-instantiate-新しい) – nawfal

答えて

32

Dictionary.Clear()は、辞書内のすべてのKeyValueペアを削除します。 new Dictionary()を実行すると、辞書の新しいインスタンスが作成されます。

古いバージョンの辞書が別の参照によってルートされていない場合にのみ、新しい辞書を作成すると辞書全体が作成され、その内容(他の場所には根付かない)がGCでクリーンアップできるようになります。

Dictionary.Clear()は、KeyValueのペアをクリーンアップに使用します。

実際には、両方のオプションは非常に類似の効果を持つ傾向があります。違いは、これはメソッド内で使用されているときに何が起こるかのようになります

void NewDictionary(Dictionary<string,int> dict) 
{ 
    dict = new Dictionary<string,int>(); // Just changes the local reference 
} 

void ClearDictionary(Dictionary<string,int> dict) 
{ 
    dict.Clear(); 
} 

// When you use this... 
Dictionary<string,int> myDictionary = ...; // Set up and fill dictionary 

NewDictionary(myDictionary); 
// myDictionary is unchanged here, since we made a new copy, but didn't change the original instance 

ClearDictionary(myDictionary); 
// myDictionary is now empty 
+2

@divo - 私は彼が参照、オブジェクト自体のコピーではありません –

+0

@ジョン:それはまさに私が意味していたものです。それはコピーです - 辞書への参照のコピー –

0

Dictionary.clearは、辞書内のすべての項目を削除します。新しいディクショナリは、ガベージコレクタが後でクリーンアップするために前のディクショナリを孤立させながら、新しいディクショナリオブジェクトをメモリに作成します。

+0

"最も可能性が高い"よりもうまくいっていますか?それはここで重要な問題になるでしょう。 –

+0

辞書にはそれに含まれるアイテムのDisposeが呼び出されるとは思わない。もしアイテムが使い捨てであれば、私はそれらを処分する明示的なコードを書くべきだと思います。 – ChrisW

+1

何故それを処分するのですか?彼らが辞書に入っているからといって、他の場所で使われていないわけではありません。それは恐ろしくバグでしょう。ハッシュテーブルバケットはnullです。 – womp

14

Dictionary.Clear()
この辞書内の全てのキー/値のペアを削除します。ガベージコレクタは、次のガベージコレクションサイクル中にこれらのアイテムのメモリをクリアします。 MSDN

新しい辞書()
メモリに新しい辞書オブジェクトを作成し、元のオブジェクトを破棄する。メモリは、次のガベージコレクションサイクル中にクリアされます。

+0

MSDNの記事は、処分について何も言及していません。 –

+3

何か考慮すべき点 - 辞書が非常に大きく、クリア後にほぼ同じ量のデータを読み込んでいることが確実であれば - Dictionary.Clear()が辞書の容量をリセットしないという事実それはより魅力的です。 – overslacked

+0

@overslacked - まあまあ私はちょうどそのことを示唆する答えを書く時間を費やした。 – womp

5

私は重要な違いは、あなたがDictionary.Clear()を呼び出す場合、その辞書へのすべての参照がクリアされることがあるとします。 new Dictionary()を使用すると、その時点で扱っている参照が(ある意味で)クリアされますが、他のすべての参照先は古い辞書を参照するため、参照されません。

うまくいけば、このコードは、単にそれを示しています

public void Method() 
{ 
    Dictionary<int, int> d1 = new Dictionary(); 

    d1.Add(1,1); 
    d1.Add(2,3); 

    Dictionary<int, int> d2 = d1; 

    //this line only 'clears' d1 
    d1 = new Dictionary(); 

    d1.Add(1,1); 
    d1.Add(3,5); 
    d2.Add(2,2); 

    //writes '2' followed by '1' 
    Console.WriteLine(d1.Count); 
    Console.WriteLine(d2.Count); 
} 

私はd1.Clear()ではなく、その後、D1、D2が同期に残っているだろう、と追加し、その後は、両方に追加しているだろうと呼ばれていた場合。 WriteLine呼び出しはどちらも代わりに '3'を出力します。

+0

+1 - これは主要な違いです。 – Joe

1

この辞書に複数の参照があり、それをクリアすると、新しい辞書を作成した場合のように、その新しい参照にのみ影響します。私はそれがあなたが目指している影響の範囲に依存すると思います。明らかに "new"への呼び出しはあなたに "クリアされた"辞書を与えますが、他の有用な状態情報を失うかもしれません。

5

Dictionary.Clearはインスタンス内のすべてのアイテムを削除しますが、new Dictionary()はまったく新しいインスタンスを作成します。両者の間には微妙な関係があるかもしれません。次の例を考えてみましょう。

void Example1() 
{ 
    var collection = new Dictionary<string, string>(); 
    collection.Add("key1", "value1"); 
    collection.Add("key2", "value2"); 
    foreach (var kvp in collection) 
    { 
    collection = new Dictionary<string, string>(); 
    Console.WriteLine(kvp); 
    } 
} 

void Example2() 
{ 
    var collection = new Dictionary<string, string>(); 
    collection.Add("key1", "value1"); 
    collection.Add("key2", "value2"); 
    foreach (var kvp in collection) 
    { 
    collection.Clear(); 
    Console.WriteLine(kvp); 
    } 
} 

最初の例では、元のコレクションのすべての内容が印刷されます。これは、列挙子が新しいインスタンスに再割り当てされる前に参照変数から作成されたためです。

2番目の例では、列挙中にコレクションがクリアされ、コレクションが変更されたためにInvalidOperationExceptionになります。

19

広範にカバーされているように、効果は本質的に同じです。 Clear()newは、両方ともあなたに新鮮な辞書を提供します。基本的には、その中のオブジェクトへの参照を放棄して、それらがルーティングされなかった場合に収集されるようにします。

.Clear()は、以前と同じサイズに辞書を再投入しようとした場合、newを超える利点があります。これは、既に内部にあるオブジェクトの数を保持するために内部的にサイズが変更されているためです。新しいディクショナリを作成すると、デフォルトのサイズの新しい内部ハッシュテーブルが作成され、アイテムを追加するときに再展開する必要があります。

また、全く異なる意図を伝えることをお勧めします。以前と同じコンテキストを扱う場合は、コードに.Clear()を使用する必要があります。新しいディクショナリを作成すると、古いディクショナリとは異なる何らかの新しいロジックを実装しようとしていることを意味しますが、Clear()を使用すると、それまでに行ったことをすべてリセットするだけでした。

+4

>新しいディクショナリを作成すると、デフォルトのサイズの新しい内部ハッシュテーブルが作成されます。必ずしもコンストラクタのオーバーロードを使用して初期容量を設定する必要はありません。 – Joe

+4

私はちょうど.Clear()対新しい辞書()を仮定していた。 – womp

3

あなたの辞書が読み取り専用のプロパティとして公開されている場合、すべてのアイテムを削除できるように、.Clear()が提供されていると思います。しかし、それがそのように公開されておらず、完全な制御権を持っていれば、新しい辞書をインスタンス化するほうが簡単かもしれません。両者のパフォーマンスに若干の違いがあるかもしれません。

関連する問題