2017-12-12 4 views
0

私はすでに公式MSDN docを読んでいます。この質問は少し異なっている - 私の代わりに理論ディクショナリ/ハスタブル壊れた注文のエッジケース(既存の例が必要です)

条件の実際の実用的な例を探しています:辞書/ hastableエントリはONLY追加することができます

  • 辞書/ hastableエントリ(最初にクリアされない限り)
  • 辞書/ハスタブルはVALUEタイプのみで動作しています
  • 辞書/ハスタブルは他の方法で変更されることはありませんが、追加要素
  • 辞書/ hastableは常に0から始まり、インデックスは簡単なコードロジック
  • て辞書のキー自体(キー名)に保存され、手動で

コードサンプルを変更されることはありません:

Dictionary<int, int> test = new Dictionary<int, int>(); 
for (int i = 0; i <= 100000; i++) 
{ 
    test.Add(i,i); 
} 
var c = 0; 
while (c < test.Count) 
{ 
    if (c != test.ElementAt(c).Key) 
    { 
     Console.WriteLine("Mismatch!"); 
     break; 
    } 
    c++; 
} 
Console.WriteLine("Test passed!"); 
//Program takes a 2hrs walk, does things, occasionally reads-only values from existing "test" collection 
for (int i = 0; i <= 500000; i++) 
{ 
    test[test.Count] = test.Count; 
} 
c = 0; 
while (c < test.Count) 
{ 
    if (c != test.ElementAt(c).Key) 
    { 
     Console.WriteLine("Mismatch!"); 
     break; 
    } 
    c++; 
} 
Console.WriteLine("Test 2 passed!"); 
//repeat some stuff 

質問:上記の厳格な規則UNDER- 辞書ランドのこの種の誰もが、実際にケースが発生しましたその要素の順序を変更しないでください。ここではMT同時コレクションについて話されていないと、再び、私は

test.ElementAt(5).keykey11115である返す単一の例I've read them.は、私が探しているものです、理論の答えに興味がないんです。

+0

'Dictionary 'のソースコードは、[ここ](http://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs,3b9a0882313262cd)にあります。 ['Enumerator.MoveNext()'](http://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs,d864a2277aad4ece,references)を見ると、 '' Dictionary 。 – dbc

+0

そして、あなたが['private void Insert(TKey key、TValue value、bool add)'](http://referencesource.microsoft.com/#mscorlib/system/collections/generic/dictionary.cs,fd1acf96113fbda9,references)を見ると、 )空きエントリがない限り、*追加されたアイテムは 'entries'配列の最後に置かれ、再ハッシングはこの順序を変更しません。だから、**この実装では、**何も削除されない限り、辞書は物事が追加される順序を保持しているようです。 – dbc

+0

**これは単なる実装の詳細です**モノラル(または将来の.Netバージョン、たとえば.Netコア3.5または.Netフル5.2など)の 'Dictionary のバージョンは書き直すことができました辞書を再ハッシュすると順序が変わるようにします。 [documentation](https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx)の唯一の約束は、次のことです。*アイテムが返される順序は未定義です*だからもっと何かに頼るのは賢明ではないでしょう。 – dbc

答えて

1

また、Dictionary<TKey, TValue>のソースコードはhereです。あなたはEnumerator.MoveNext()を見れば、あなたはそれが順番に配列dictionary.entriesを反復処理していることがわかります。

while ((uint)index < (uint)dictionary.count) { 
    if (dictionary.entries[index].hashCode >= 0) { 
     current = new KeyValuePair<TKey, TValue>(dictionary.entries[index].key, dictionary.entries[index].value); 
     index++; 
     return true; 
    } 
    index++; 
} 

をそして、あなたは(両方の項目を追加し、設定したときに呼び出される)private void Insert(TKey key, TValue value, bool add)を見れば、あなたはそのは限り表示されます

private void Insert(TKey key, TValue value, bool add) {  
// Snip 
    int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; 
    int targetBucket = hashCode % buckets.Length; 

// Snip 
    for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next) { 
     if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) { 
// Key found. Set the new value at the old location in the entries array. 
      if (add) { 
       ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate); 
      } 
      entries[i].value = value; 
      version++; 
      return; 
     } 
     // Snip 
    } 
// Key not found, add to the dictionary. 
    int index; 
    if (freeCount > 0) { 
// Free entries exist because items were previously removed; recycle the position in the entries array. 
     index = freeList; 
     freeList = entries[index].next; 
     freeCount--; 
    } 
    else { 
// No free entries. Add to the end of the entries array, resizing if needed. 
     if (count == entries.Length) 
     { 
      Resize(); 
      targetBucket = hashCode % buckets.Length; 
     } 
     index = count; 
     count++; 
    } 

// Set the key and value in entries array. 
    entries[index].hashCode = hashCode; 
    entries[index].next = buckets[targetBucket]; 
    entries[index].key = key; 
    entries[index].value = value; 
    buckets[targetBucket] = index; 
// Snip remainder 

(すなわち何も除去されていない)空きエントリがないように、キーが見つかった場合、キーが見つかった、または現在の位置にない場合、項目はentriesアレイの端部に配置されています最後に、をチェックすると、辞書を焼き直しするために呼び出されるメソッドは、あなたがentries配列が保存されるの順番がわかります。したがって、私たちはこの実装としている限り、何も削除されていないと言うことができる

Array.Copy(entries, 0, newEntries, 0, count); 

辞書ジャムキーが追加される順序

これは単なる実装の詳細です。モノ(または将来の.Netバージョン、たとえば.Netコア3.5または.Net full 5)のバージョンDictionary<TKey, TValue>。2など)は、辞書を再ハッシュして順序を変更するように書き直すことができます。 documentationの唯一の約束は、です。返されるアイテムの順序は定義されていません。これ以上のものに頼るのは賢明ではありません。

関連する問題