web-dev-qa-db-ja.com

C#で辞書を読み取り専用にする

Dictionary<string, List<string>>があり、メンバーを読み取り専用として公開したい。 IReadOnlyDictionary<string, List<string>>として返すことができますが、IReadOnlyDictionary<string, IReadOnlyList<string>>として返す方法がわかりません。

これを行う方法はありますか? C++ではconstを使用するだけですが、C#にはありません。

この場合、単にIReadOnlyDictionaryを使用しても役に立ちません。値も読み取り専用にする必要があるためです。これを行う唯一の方法は、別のIReadOnlyDictionaryをビルドし、それらにIReadOnlyListを追加することだけです。

別のオプションは、私は興奮しませんが、インターフェイスIReadOnlyDictionary>を実装するラッパーを作成し、元のインスタンスのコピーを保持することですが、それはやり過ぎです。

10
bpeikes

具体的には読み取り専用_Dictionary<string, List<string>>_を探しているという事実を考えると、基本的に Lookup を正確に探しています。

DictionaryオブジェクトにはToLookup()拡張があります。

5
John Bustos

まず、目的のコンテンツタイプで新しい辞書を作成する必要があります。

var dicWithReadOnlyList = dic.ToDictionary(
    kv => kv.Key,
    kv => kv.Value.AsReadOnly());

IReadOnlyDictionaryDictionaryのスーパータイプであるため、新しい辞書を返すことができます。


なぜそうする必要があるのですか? Dictionary<T, A>Dictionary<T, B>のスーパータイプではないため、ifAB。どうして?次の例を考えてみましょう。

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.

つまり、TValueDictionary共変ではない 。オブジェクト指向の観点からは、辞書の読み取り専用バージョンでは共分散shouldが可能ですが、.NETにはレガシーな問題がありますこれを防ぐフレームワーク(詳細は this question の "UPDATE"で始まる部分を参照)。

2
Heinzi

読み取り専用の辞書を返したいが、クラス内の辞書とリストを変更できる場合は、キャストを使用してリストタイプを取得できます。

この例は少し工夫されていますが、どのように機能するかを示しています。

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を使用するのが最適なオプションです。

0
Patrick Huber