c# - नेस्टेड शब्दकोश को IReadOnlyDictionary में परिवर्तित करना




collections .net-4.5 (2)

मैं आंतरिक संग्रह ऑब्जेक्ट के लिए IReadOnly- संदर्भ देने की कोशिश कर रहा हूँ यह ज्यादातर मामलों में अच्छी तरह से काम करता है, लेकिन अगर मैं एक शब्दकोश में एक संग्रह जिसमें एक IReadOnlyDictionary में एक IReadOnlyCollection युक्त परिवर्तित करने के लिए चाहता हूँ नहीं है।

यहाँ एक कोड उदाहरण:

    var list = new List<int>();
    IReadOnlyList<int> listReference = list; //works;

    var dictionary = new Dictionary<int, int>();
    IReadOnlyDictionary<int, int> dictionaryReference = dictionary; //works

    var nestedList = new List<List<int>>();
    IReadOnlyList<IReadOnlyList<int>> nestedReadOnlyListReference = nestedList; //works

    var nestedDictionary = new Dictionary<int, List<int>>();
    //IReadOnlyDictionary<int, IReadOnlyList<int>> nestedReadOnlyDictionaryReference = nestedDictionary; //does not work, can not implicitly convert

    //current workaround
    var nestedDictionaryReferenceHelper = new Dictionary<int, IReadOnlyList<int>>();
    foreach (var kvpNestedDictionary in nestedDictionary)
    {
        nestedDictionaryReferenceHelper.Add(kvpNestedDictionary.Key, (IReadOnlyList<int>)kvpNestedDictionary.Value);
    }
    IReadOnlyDictionary<int, IReadOnlyList<int>> nestedReadOnlyDictionaryReference = nestedDictionaryReferenceHelper; //works, but is only a reference to the internal List, not to the dictionary itself

nestedDictionary बहुत बदसूरत है क्योंकि इसे अतिरिक्त स्मृति की आवश्यकता होती है और हर बार nestedDictionary बदलावों के मूल्यों को अद्यतन करने की आवश्यकता nestedDictionary है।

ऐसे नेस्टेड शब्दकोशों को बदलने का कोई आसान तरीका है?


मेरी राय में यह बात है कि आप अपनी खुद की गरिमा के साथ एक उचित नए प्रकार पेश करने का अवसर खो रहे हैं। यदि आप Dictionary<int, List<int>> का उपयोग कर रहे हैं तो आप अपने आप को कोड के साथ देखेंगे जैसे कि हर बार जब आपको कोई मान सम्मिलित करने की आवश्यकता होती है:

if (!_dictionary.ContainsKey(key)) {
    var list = new List<int>();
    list.Add(value);
    _dictionary.Add(key, list);
} else {
    _dictionary[key].Add(value);
}

और जब आप एक मान की खोज करना चाहते हैं, तो कोड के साथ भी बदतर हो:

_dictionary.ContainsKey(key) && _dictionary[key].Contains(value);

और उन उदाहरणों की विविधता क्या बदतर है आप इस कार्यान्वयन के विस्तार को अपने वर्ग उपयोगकर्ताओं को उजागर कर रहे हैं। यदि यह विवरण बदल जाएगा तो आप सभी कोड को तोड़ देंगे क्या, उदाहरण के लिए, यदि आप HashSet<int> साथ List<int> को बदलना चाहते हैं?

यह कैसा होना चाहिए?

_multimap.Add(key, value);

एक उचित इंटरफ़ेस के साथ (यहां मैं कुछ ही तरीके दिखाता हूं):

public interface IMultiMap<TKey, TValue> {
    void Add(TKey key, TValue value);
    bool ContainsKey(TKey key);
}

और इसका कार्यान्वयन:

public sealed class MultiMap<TKey, TValue> : IMultiMap<TKey, TValue> {
    // ...

    private Dictionary<int, List<int>> _items;
}

आप IReadOnlyMultiMap<TKey, TValue> परिचय कर सकते हैं:

public interface IReadOnlyMultiMap<TKey, TValue> {
    bool ContainsKey(TKey key);
}

बस IReadOnlyMultiMap<TKey, TValue> MultiMap<TKey, TValue> IReadOnlyMultiMap<TKey, TValue> MultiMap<TKey, TValue> IReadOnlyMultiMap<TKey, TValue> को MultiMap<TKey, TValue> और एक पठन-केवल संग्रह को वापस करने के लिए आपको कुछ नहीं करना है (काल्पनिक उदाहरण):

IReadOnlyMultiMap<int, int> MakeReadOnly(MultiMap<int, int> map) {
    return map; // Nothing to do!
}

ध्यान दें कि आप एक नया MultiMap<TKey, TValue> को लाइव संग्रह में कॉल करने के लिए सुरंग को कॉल करने के लिए कॉल करने से बचने के लिए (केवल MultiMap<TKey, TValue> को केवल-पढ़ने की सीमा को दरकिनार करने के लिए कॉल करना शुरू कर सकते हैं) अवधारणा के सुबूत:

public sealed class ReadOnlyMultiMap<TKey, TValue> : IReadOnlyMultiMap<TKey, TValue> {
    public ReadOnlyMultiMap(IMultiMap<TKey, TValue> collection) {
        _collection = collection;
    }

    public bool ContainsKey(TKey key) {
        return _collection.ContainsKey(key);
    }

    private readonly IMultiMap<TKey, TValue> _collection;
}

केवल पढ़ने के लिए केवल देखने के लिए आप ऐसा करते हैं:

IReadOnlyMultiMap<int, int> MakeReadOnly(MultiMap<int, int> map) {
    return new ReadOnlyMultiMap<int, int>(map);
}

ध्यान दें कि मैंने कार्यान्वयन विवरण के बारे में बताया । आप अभी भी एक कार्यान्वयन विवरण (आप एक multimap का उपयोग कर रहे हैं) को उजागर कर रहे हैं, यदि ऐसा कोड सार्वजनिक एपीआई के लिए है तो आपको यह वर्णन करने के लिए एक नया (ठीक प्रकार से नामित) प्रकार प्रस्तुत करना चाहिए , यह नहीं कि भंडारण कैसे लागू होता है यह हो सकता है MeasureCollection , SoccerScoreCollection या जो भी आपके मॉडल के बारे में बात कर रहे हैं, भंडारण भिन्न हो सकता है लेकिन सामग्री नहीं होगी


रूपांतरण में असफल होने की समस्या है किवॉल्यूपायरः यद्यपि क्लास बेस क्लास बेस में प्राप्त किया जाता है, लेकिन केवल्यूपियर कुंजीवॉल्यूपियर का उप वर्ग नहीं है; परिभाषाएं देखें ( शब्दकोश , IReadOnlyDictionary )

तो आपको हमेशा किसी प्रकार के समाधान की आवश्यकता होगी (मल्टीमैप दृष्टिकोण मुझे एक के रूप में दिखाई देता है, भी ...)। यदि nestedDictionary निजी है, तो आपके पास इसके पर अपने क्लास से पूरा नियंत्रण है, आप इस के साथ दूर हो सकते हैं:

var nestedDictionary = new Dictionary<int, IReadOnlyList<int>>();
IReadOnlyDictionary<int, IReadOnlyList<int>> nestedReadOnlyDictionaryReference = nestedDictionary;

और जब भी सूची के भीतर एक सूची को संशोधित करता है, तो List<int> डाली लगाने के लिए एक और बदसूरत कार्यवाही, मैं स्वीकार करता हूं, लेकिन अतिरिक्त स्मृति और अतिरेक प्रबंधन को बचाता है और IReadOnlyDictionary<int, IReadOnlyList<int>> सार्वजनिक इंटरफ़ेस (asumed ...) को बरकरार रखता है।

संपादित करें: सिर्फ एक विचार है, परीक्षण नहीं किया है, लेकिन यह काम कर सकता है : केवल पढ़ने के लिए शब्दकोश के लिए असाइन करने के लिए लापता इंटरफेस जोड़ने में अपना स्वयं का शब्दकोश है:

public class MyDictionary
    : Dictionary<int, List<int>>,
      ICollection<KeyValuePair<int, IReadOnlyList<int>>,
      IEnumerable<KeyValuePair<int, IReadOnlyList<int>>, 
      IReadOnlyCollection<KeyValuePair<int, IReadOnlyList<int>>
{
}

मैं अभी भी कार्यान्वित करने के लिए एक इंटरफ़ेस को खो दिया है, और आपको अभी तक कुछ सदस्यों को लागू करना पड़ सकता है यदि यह काम करता है, तो संभवतः साफ समाधान ...





readonly