0

私が取り組んでいるプロジェクトのコードの安全性とコードの読みやすさ/視覚への影響に関して、内部 Dictionary インスタンス (C#) への参照を返すための 3 つのアプローチを検討しています。

次の 3 つのアプローチに絞り込みましたが、より良い提案をお待ちしています。現在、追加のボイラー プレートを使用せずに安全性を確保するための最良のバランスとして、#3を好みます。

1) 2 番目の ReadOnlyDictionary インスタンスを使用して内部 Dictionary をラップし、ReadOnlyDictionary だけがクラスをエスケープできるようにします。

2) Dictionary インスタンスを IReadOnlyDictionary として返しますが、再キャストすると変更される可能性があるため、オプション #1 または #3 ほど安全ではありません。

3) Dictionary.ToImmutableDictionary() を含むクラスをエスケープするときに ImmutableDictionary として返すため、返されるオブジェクトは内部辞書の不変ビューになりますが、これにより、より高いコストが発生するすべての呼び出しに対して新しいコピーが作成されます。小さな簡単な辞書(私のもの)を使用します。

    private readonly Dictionary<string, string> innerDictionary = new Dictionary<string, string>();

    // Only required for Example #1
    private readonly IReadOnlyDictionary<string, string> readonlyInnerDictionary;

    public ExampleClass() {
        // Only required for Example #1
        readonlyInnerDictionary = new ReadOnlyDictionary<string, string>(innerDictionary);
    }   

    public IReadOnlyDictionary<string, string> GetExampleOne() {
        // Requires a second dictionary which is more boiler plate but the object being returned is truly readonly
        return readonlyInnerDictionary;     
    }

    public IReadOnlyDictionary<string, string> GetExampleTwo() {
        // Requires InnerDictionary be defined as Dictionary (Not IDictionary) but doesn't require the second dictionary be defined
        // which is less boiler plate, but the object returned could be re-cast to it's mutable form meaning it's not truly mutation safe.
        return innerDictionary;
    }

    public ImmutableDictionary<string, string> GetExampleThree() {
        // Truly immutable object returned, but a new instance is built for every call; fortunately all of my dictionaries are small (containing at most 9 keys)
        return innerDictionary.ToImmutableDictionary();
    }
4

2 に答える 2

2

オプション 1 が有効です。ReadOnlyDictionary を IDictionary に再キャストできますが、変更しようとすると例外がスローされます。

 void CastingTest()
        {
            var dic1 = new Dictionary<string, string>();
            dic1.Add("Key", "Value");
            var dic2 = new ReadOnlyDictionary<string, string>(dic1);
            var castedDic = (IDictionary<string, string>)dic2;
            castedDic.Add("AnotherKey", "Another Value"); //System.NotSupportedException, Collection is read only
        }

ReadOnlyDictionary は別の Dictionary を作成しません。最初のものと同じ参照を指し、それをカプセル化します。したがって、次のようにします。

void AddTest()
        {
            var dic1 = new Dictionary<string, string>();
            dic1.Add("Key", "Value");
            var dic2 = new ReadOnlyDictionary<string, string>(dic1);
            dic1.Add("Key2", "Value2"); //Now dic2 have 2 values too.
        }

innerDictionary を決して公開しないでください。問題ありません。

于 2016-09-02T14:54:02.167 に答える
0

最もきれいで、簡単で、安全であると判断しました。しかし、最もパフォーマンスの高い解決策は、 (から)ConcurrentDictionaryスレッドセーフを保証する を内部的に使用してから、内部クラスをエスケープする辞書を作成するto 呼び出しを使用することです。インターフェイス署名は.System.Collections.ConcurrentSystem.Collections.Immutabledictionary.ToImmutableDictionary()ImmutableDictionary<KeyType, ValueType>

これは最もパフォーマンスの高いソリューションではありませんが、私の場合、12 個未満のキーと状態を表す小さな単純なオブジェクトを持つ辞書を使用する場合、ほとんどの場合、これは問題ではありません。

于 2016-09-09T13:18:53.667 に答える