क्या KeyedCollection में कुंजी के लिए int का उपयोग करना ठीक है

अक्सर मुझे संख्यात्मक पहचानकर्ताओं के साथ गैर-अनुक्रमिक वस्तुओं का संग्रह करने की आवश्यकता होती है। मुझे इसके लिए कीडकोलेक्शन का उपयोग करना पसंद है, लेकिन मुझे लगता है कि एक गंभीर कमी है। यदि आप कुंजी के लिए int का उपयोग करते हैं, तो आप अब उनके इंडेक्स द्वारा संग्रह के सदस्यों तक नहीं पहुंच सकते हैं (संग्रह [अनुक्रमणिका] अब वास्तव में संग्रह [कुंजी] है)। क्या कुंजी के रूप में int का उपयोग करने से बचने के लिए यह एक गंभीर समस्या है? एक बेहतर विकल्प क्या होगा? (शायद int.ToString ()?)

मैंने बिना किसी बड़ी समस्या के पहले यह किया है, लेकिन हाल ही में मैंने एक बुरा स्नैग मारा जहां एक कीड कोलेक्शन के खिलाफ एक्सएमएल सीरियलाइजेशन नहीं काम करता है यदि कुंजी एक int है, .NET में एक बग

11

4 उत्तर

असल में आपको यह तय करने की ज़रूरत है कि कक्षा के उपयोगकर्ताओं को इस तथ्य से भ्रमित होने की संभावना है कि वे नहीं कर सकते हैं, उदाहरण के लिए, ऐसा करें:

for(int i=0; i=< myCollection.Count; i++)
{
    ... myCollection[i] ...
}

हालांकि वे निश्चित रूप से foreach का उपयोग कर सकते हैं, या एक कास्ट का उपयोग कर सकते हैं:

for(int i=0; i=< myCollection.Count; i++)
{
    ... ((Collection)myCollection)[i] ...
}

यह एक आसान निर्णय नहीं है, क्योंकि यह आसानी से हेज़ेनबग का नेतृत्व कर सकता है। मैंने इसे अपने ऐप्स में से किसी एक में अनुमति देने का निर्णय लिया, जहां कक्षा के उपयोगकर्ताओं से पहुंच मुख्य रूप से कुंजी द्वारा थी।

I'm not sure I'd do so for a shared class library though: in general I'd avoid exposing a KeyedCollection in a public API: instead I would expose IList in a public API, and consumers of the API who need keyed access can define their own internal KeyedCollection with a constructor that takes an IEnumerable and populates the collection with it. This means you can easily build a new KeyedCollection from a list retrieved from an API.

क्रमबद्धता के संबंध में, एक प्रदर्शन समस्या भी है जो मैंने माइक्रोसॉफ्ट कनेक्ट की सूचना दी : कीड कोलेक्शन एक आंतरिक शब्दकोश के साथ-साथ एक सूची बनाए रखता है, और दोनों को क्रमबद्ध करता है - यह सूची को क्रमबद्ध करने के लिए पर्याप्त है क्योंकि शब्दकोश को आसानी से deserialization पर पुनर्निर्मित किया जा सकता है।

इस कारण के साथ-साथ XmlSerialization बग, मैं आपको एक KeyedCollection को क्रमबद्ध करने से बचने की सलाह दूंगा - इसके बजाय केवल KeyedCollection.Items सूची को क्रमबद्ध करें।

मुझे किसी अन्य प्रकार में अपनी int कुंजी लपेटने का सुझाव । ऐसा लगता है कि जटिलता को जोड़ने में मुझे गलत लगता है ताकि एक प्रकार को किसी कुंजी के रूप में एक कुंजी के रूप में उपयोग किया जा सके। मैं ऐसा करने के बजाय एक स्ट्रिंग कुंजी (ToString) का उपयोग करता हूं - यह वीबी 6 संग्रह वर्ग की तरह है।

एफडब्ल्यूआईडब्ल्यू, मैंने पूछा कुछ समय पहले एमएसडीएन मंचों पर एक ही सवाल । FxCop टीम के एक सदस्य से एक प्रतिक्रिया है, लेकिन कोई निर्णायक दिशानिर्देश नहीं है।

7
जोड़ा
आप थ्रेसहोल्ड = -1 के माध्यम से शब्दकोश को अक्षम कर सकते हैं
जोड़ा लेखक paparazzo, स्रोत
मुझे लगता है कि मैं एक कुंजीपटल चयन को उजागर करने के साथ सहमत हूं जो एपीआई में कुंजी के लिए int का उपयोग करता है। यह शायद दूसरे छोर पर कीड़े का कारण बन जाएगा। क्रमबद्धता मुद्दे निश्चित रूप से संग्रह को क्रमबद्ध करने के लिए एक अच्छा कारण नहीं है, बल्कि केवल आइटम (जो मैंने अपने मामले में किया था)।
जोड़ा लेखक Jon B, स्रोत
विशेष रूप से पूर्णांक कुंजी के लिए KeyedCollection से व्युत्पन्न कक्षा का उपयोग करने का दृष्टिकोण भी है जिसमें उपयुक्त आइटम प्राप्त करने के लिए आंतरिक आइटम संग्रह का उपयोग करने वाले GetByIndex या ItemAt विधि शामिल हैं। यह आपको नीचे दिए गए दृष्टिकोण के बजाय मौजूदा कीड कोलेक्शन का लाभ उठाने देता है जिसमें संग्रह को बढ़ाने में शामिल है।
जोड़ा लेखक Thomas S. Trias, स्रोत

ओवरलोड रिज़ॉल्यूशन के लिए एक अलग प्रकार बनाने के लिए int को दूसरे प्रकार में लपेटना एक आसान समाधान हो सकता है। यदि आप struct का उपयोग करते हैं, तो इस रैपर में कोई अतिरिक्त ओवरहेड नहीं है:

struct Id {
    public int Value;

    public Id(int value) { Value = value; }

    override int GetHashCode() { return Value.GetHashCode(); }

   //… Equals method.
}
3
जोड़ा
यह एक अच्छा विचार है। हालांकि, यह हमेशा एक अच्छा विचार है कि structs अपरिवर्तनीय बनाने के लिए। यह निम्नलिखित की तरह भ्रम से बचाता है: आईडी आईडी; id.Value = 2; आईडी आईडी 2 = आईडी; id2.Value = 4;//आईडी क्या है। इसके बाद वाल्यू? बहुत से लोग उम्मीद करेंगे 4. (प्रारूपण के लिए खेद है; अगर मैं कर सकता तो मैं लाइन ब्रेक का उपयोग करूंगा)
जोड़ा लेखक Neil, स्रोत

It might be best to add a GetById(int) method to a collection type. Collection can be used instead if you don't need any other key for accessing the contained objects:

public class FooCollection : Collection
 { Dictionary dict = new Dictionary();

   public Foo GetById(int id) { return dict[id]; }

   public bool Contains(int id) { return  dict.Containskey(id);}

   protected override void InsertItem(Foo f)
    { dict[f.Id] = f;
      base.InsertItem(f);
    }

   protected override void ClearItems()
    { dict.Clear();
      base.ClearItems();
    }

   protected override void RemoveItem(int index)
    { dict.Remove(base.Items[index].Id);
      base.RemoveItem(index);
    }

   protected override void SetItem(int index, Foo item)
    { dict.Remove(base.Items[index].Id);
      dict[item.Id] = item;
      base.SetItem(index, item);
    }
 }









 }
2
जोड़ा
यह सबसे अच्छा जवाब इमो है
जोड़ा लेखक nawfal, स्रोत

KeyedCollection में कुंजी को एकत्रित किए जा रहे ऑब्जेक्ट से अद्वितीय और तेज़ी से व्युत्पन्न होना चाहिए। एक व्यक्ति वर्ग को देखते हुए, उदाहरण के लिए, यह एसएसएन संपत्ति हो सकती है या शायद फर्स्टनाम और लास्टनाम गुणों को भी संयोजित कर सकती है (यदि परिणाम अद्वितीय होने के लिए जाना जाता है)। यदि कोई आईडी कानूनी रूप से उस वस्तु के क्षेत्र से एकत्रित की जाती है जो कुंजी के लिए वैध उम्मीदवार है। लेकिन टक्कर से बचने के लिए शायद इसे एक स्ट्रिंग के रूप में कास्ट करने का प्रयास करें।

1
जोड़ा