辞書を適切にカプセル化する方法の完全な例を見つけることができませんでした。私がしたい/したいのは、仮想ではないのでオーバーライドできないことがわかっているAddメソッドを「オーバーライド」することだけでした。いくつかの調査に基づいて、プライベートディクショナリを使用してIDictionaryインターフェイスを実装する必要があることがわかりました。
私が見つけた最も完全な例はここにあり、ほとんどコピーして貼り付けて、一致しなかったものについて推測しました(この例は読み取り専用辞書を実装していますが、カスタマイズされたAdd()メソッドを使用した完全なデフォルト機能が必要です) 。
以下の完全なコンパイル可能なコード:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace IDictionary
{
class Program
{
static void Main(string[] args)
{
Registers<string, dynamic> DynRegistry = new Registers<string, dynamic>();
DynRegistry.Add("Foo", 100);
Console.WriteLine("DynRegistry Size: {0}", DynRegistry.Count);
foreach (var item in DynRegistry)
{
Console.WriteLine("\tName: {0}, Value: {1}", item.Key, item.Value);
}
DynRegistry.Add("Foo2", "Hello World");
Console.WriteLine("DynRegistry Size: {0}", DynRegistry.Count);
foreach (var item in DynRegistry)
{
Console.WriteLine("\tName: {0}, Value: {1}", item.Key, item.Value);
}
DynRegistry.Add("Foo", true);
Console.WriteLine("DynRegistry Size: {0}\r\n", DynRegistry.Count);
foreach (var item in DynRegistry)
{
Console.WriteLine("\tName: {0}, Value: {1}", item.Key, item.Value);
}
Console.ReadKey();
}
}
class Registers<TKey, TValue> : IDictionary<TKey, TValue>, ICollection
{
//Fields
private Dictionary<TKey, TValue> source;
private object syncRoot;
//Constructor
public Registers()
{
this.source = new Dictionary<TKey, TValue>();
}
//Wrapped Methods
public void Add(TKey key, TValue value)
{
if (this.source.ContainsKey(key))
{
this.source[key] = value;
}
else
{
this.source.Add(key, value);
}
}
//Implement default Interfaces
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
ICollection<KeyValuePair<TKey, TValue>> collection = this.source;
collection.CopyTo(array, arrayIndex);
}
public int Count { get { return this.source.Count; } }
public ICollection<TKey> Keys { get { return this.source.Keys; } }
public ICollection<TValue> Values { get { return this.source.Values; } }
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly { get { return false; } }
bool ICollection.IsSynchronized { get { return false; } }
object ICollection.SyncRoot
{
get
{
if (this.syncRoot == null)
{
ICollection collection = this.source as ICollection;
if (collection != null)
{
this.syncRoot = collection.SyncRoot;
}
else
{
Interlocked.CompareExchange(ref this.syncRoot, new object(), null);
}
}
return this.syncRoot;
}
}
public TValue this[TKey key]
{
get { return this.source[key]; }
set { this.source[key] = value; }
}
public bool ContainsKey(TKey key) { return this.source.ContainsKey(key); }
public bool Remove(TKey key) { return this.source.Remove(key); }
public bool TryGetValue(TKey key, out TValue value) { return this.source.TryGetValue(key, out value); }
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
{
ICollection<KeyValuePair<TKey, TValue>> collection = this.source;
collection.Add(item);
}
void ICollection<KeyValuePair<TKey, TValue>>.Clear()
{
ICollection<KeyValuePair<TKey, TValue>> collection = this.source;
collection.Clear();
}
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
ICollection<KeyValuePair<TKey, TValue>> collection = this.source;
return collection.Contains(item);
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
ICollection<KeyValuePair<TKey, TValue>> collection = this.source;
return collection.Remove(item);
}
void ICollection.CopyTo(Array array, int index)
{
ICollection collection = new List<KeyValuePair<TKey, TValue>>(this.source);
collection.CopyTo(array, index);
}
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
IEnumerable<KeyValuePair<TKey, TValue>> enumerator = this.source;
return enumerator.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.source.GetEnumerator();
}
}
}
私がこれを投稿する2つの理由:
- そのため、これを行う必要がある他の人は、冗長なコードを再入力するのに30分を費やす必要はありません。
- 私がこれをすべて正しく行ったかどうかについてのフィードバック。ICollectionインターフェイスを実装する必要があるかどうか/なぜ実装する必要があるのか混乱しました(つまり、通常の辞書でこれを実行するのか、それともIDictionaryにICollectionを必要とせずに辞書機能を完全に補完するのか)。
私が本当に必要としたのは、Addの代わりにAddOrReplace()を実行するAddメソッドを備えた通常の辞書でした(または、キーがすでに存在するためにクラッシュします)。これを達成するために必要な作業は少しやり過ぎのようでした。