Dictionary<string, List<string>>
があり、メンバーを読み取り専用として公開したい。 IReadOnlyDictionary<string, List<string>>
として返すことができますが、IReadOnlyDictionary<string, IReadOnlyList<string>>
として返す方法がわかりません。
これを行う方法はありますか? C++ではconstを使用するだけですが、C#にはありません。
この場合、単にIReadOnlyDictionary
を使用しても役に立ちません。値も読み取り専用にする必要があるためです。これを行う唯一の方法は、別のIReadOnlyDictionaryをビルドし、それらにIReadOnlyListを追加することだけです。
別のオプションは、私は興奮しませんが、インターフェイスIReadOnlyDictionary>を実装するラッパーを作成し、元のインスタンスのコピーを保持することですが、それはやり過ぎです。
具体的には読み取り専用_Dictionary<string, List<string>>
_を探しているという事実を考えると、基本的に Lookup を正確に探しています。
DictionaryオブジェクトにはToLookup()
拡張があります。
まず、目的のコンテンツタイプで新しい辞書を作成する必要があります。
var dicWithReadOnlyList = dic.ToDictionary(
kv => kv.Key,
kv => kv.Value.AsReadOnly());
IReadOnlyDictionary
はDictionary
のスーパータイプであるため、新しい辞書を返すことができます。
なぜそうする必要があるのですか? Dictionary<T, A>
はDictionary<T, B>
のスーパータイプではないため、ifA
はB
。どうして?次の例を考えてみましょう。
var dic = new Dictionary<T, B>();
Dictionary<T, A> dic2 = dic; // Imagine this were possible...
dic2.Add(someT, someA); // ...then we'd have a type violation here, since
// dic2 = dic requires some B as the value.
つまり、TValue
のDictionary
共変ではない 。オブジェクト指向の観点からは、辞書の読み取り専用バージョンでは共分散shouldが可能ですが、.NETにはレガシーな問題がありますこれを防ぐフレームワーク(詳細は this question の "UPDATE"で始まる部分を参照)。
読み取り専用の辞書を返したいが、クラス内の辞書とリストを変更できる場合は、キャストを使用してリストタイプを取得できます。
この例は少し工夫されていますが、どのように機能するかを示しています。
public class MyClass
{
Dictionary<string, IReadOnlyList<string>> _dictionary;
public IReadOnlyDictionary<string, IReadOnlyList<string>> Dictionary { get { return _dictionary; } }
public MyClass()
{
_dictionary = new Dictionary<string, IReadOnlyList<string>>();
}
public void AddItem(string item)
{
IReadOnlyList<string> readOnlyList = null;
List<string> list = null;
if (!_dictionary.TryGetValue(item, out readOnlyList))
{
list = new List<string>();
_dictionary.Add(item, list);
}
else
list = readOnlyList as List<string>;
list.Add(item);
}
}
プロパティを不変にすることが目標の場合、ReadOnlyDictionaryを使用するのが最適なオプションです。