私はしばしば Dictionary
を重要な値のクラス(例 List
)で作成し、常に同じコードを書いていますデータを入力するときのパターン。
例えば:
var dict = new Dictionary<string, List<string>>();
string key = "foo";
string aValueForKey = "bar";
つまり、キー"bar"
に対応するリストに"foo"
を挿入します。ここで、キー"foo"
は何にもマップされていない可能性があります。
これは私がいつも繰り返すパターンを使うところです:
List<string> keyValues;
if (!dict.TryGetValue(key, out keyValues))
dict.Add(key, keyValues = new List<string>());
keyValues.Add(aValueForKey);
これを行うよりエレガントな方法はありますか?
この質問に対する回答がない関連質問:
これについては少し異なりますが、効果は同じです。
_public static TValue GetOrCreate<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key)
where TValue : new()
{
TValue val;
if (!dict.TryGetValue(key, out val))
{
val = new TValue();
dict.Add(key, val);
}
return val;
}
_
呼ばれる:
_var dictionary = new Dictionary<string, List<int>>();
List<int> numbers = dictionary.GetOrCreate("key");
_
これは、パラメーターなしのパブリックコンストラクターwhere TValue : new()
の汎用制約を利用します。
発見を助けるために、拡張メソッドが狭い問題にかなり特定されていない限り、拡張メソッドは、拡張している型の名前空間に配置する傾向があります。この場合、
_namespace System.Collections.Generic
_
ほとんどの場合、型を使用する人はusing
ステートメントを最初に定義しているため、IntelliSenseはコードで定義されているその拡張メソッドも見つけます。
非常に多くのプログラミングの問題と同様に、何かを頻繁に実行している場合は、それをメソッドにリファクタリングします。
public static void MyAdd<TKey, TCollection, TValue>(
this Dictionary<TKey, TCollection> dictionary, TKey key, TValue value)
where TCollection : ICollection<TValue>, new()
{
TCollection collection;
if (!dictionary.TryGetValue(key, out collection))
{
collection = new TCollection();
dictionary.Add(key, collection);
}
collection.Add(value);
}
そして、これはどうですか?
var keyValues = dictionary[key] = dictionary.ContainsKey(key) ? dictionary[key] : new List<string>();
keyValues.Add(aValueForKey);
.Net Coreを使用する場合は、 Dictionary<>.TryAdd()
を使用できます。
var dict = new Dictionary<string, string>();
dict.TryAdd("foo", "bar"); // returns bool whether it added or not feel free to ignore.
var myValue = dict["foo"];
OK、別のアプローチ:
public static bool TryAddValue<TKey,TValue>(this System.Collections.Generic.IDictionary<TKey,List<TValue>> dictionary, TKey key, TValue value)
{
// Null check (useful or not, depending on your null checking approach)
if (value == null)
return false;
List<TValue> tempValue = default(List<TValue>);
try
{
if (!dictionary.TryGetValue(key, out tempValue))
{
dictionary.Add(key, tempValue = new List<TValue>());
}
else
{
// Double null check (useful or not, depending on your null checking approach)
if (tempValue == null)
{
dictionary[key] = (tempValue = new List<TValue>());
}
}
tempValue.Add(value);
return true;
}
catch
{
return false;
}
}
このようにして、値をジェネリックリスト(明らかにジェネリックコレクションに一般化可能)に「追加してみて」、nullチェックを行い、ディクショナリ内の既存のキー/値を取得する必要があります。使用法と例:
var x = new Dictionary<string,List<string>>();
x.TryAddValue("test", null); // return false due to null value. Doesn't add the key
x.TryAddValue("test", "ok"); // it works adding the key/value
x.TryAddValue("test", "ok again"); // it works adding the value to the existing list
それが役に立てば幸い。