List (T का) और Collection (T का) में क्या अंतर है?


93

मैंने उन्हें बहुत सारे तरीकों से इस्तेमाल करते हुए देखा है, और मुझे चिंता है कि मैं डिजाइन में एक पथ से नीचे जाने वाला हूं जो इस बेहतर नहीं होने पर अपरिवर्तनीय है। इसके अलावा, मैं .NET का उपयोग कर रहा हूं।

जवाबों:


50

Collection<T>चारों ओर एक अनुकूलन योग्य आवरण है IList<T>। जबकि IList<T>सील नहीं है, यह कोई अनुकूलन अंक प्रदान नहीं करता है। Collection<T>डिफ़ॉल्ट IList<T>तरीके मानक विधियों को सौंप दिए गए हैं , लेकिन आप जो चाहते हैं उसे करने के लिए आसानी से ओवरराइड किया जा सकता है। यह भी संभव है Collection<T>कि मैं इलिस्ट के साथ ऐसा न कर सकूं कि मेरे अंदर की घटनाओं को तार-तार करना संभव है ।

संक्षेप में, इस तथ्य के बाद इसे बढ़ाना बहुत आसान है, जो संभावित रूप से बहुत कम रिफैक्टिंग का मतलब हो सकता है।


@Marc Gravell, @Adam Lassek: हम इन्सटाइटेम (...) विधि को किसी सार्वजनिक शून्य नए सम्मिलन (...) के साथ छिपाकर और फिर आधार को कॉल करके सूची के साथ एक ही कार्य नहीं कर सकते। ।) अंदर से ? यह अभी भी अनुबंध नहीं तोड़ता। (सूची में नाम 'इन्सर्ट' है, लेकिन फिर भी) तो कलेक्शन <टी> से चिपके रहने में क्या बड़ी बात है?
डेस्टेकऑवरफ्लो

4
@DeeStackOverflow - क्योंकि विधि छिपाने का उपयोग किसी भी कोड द्वारा नहीं किया जाएगा जो एक अलग एपीआई का उपयोग करता है - अर्थात IList, जो कुछ भी दिखता है IList<T>, List<T>आदि। संक्षेप में, आपको पता नहीं है कि क्या इसे कहा जाएगा। बहुरूपता इसे ठीक करता है।
मार्क Gravell

@AdamLassek: आप अपने जवाब में ObservableCollection<T>एक उदाहरण के रूप में जोड़ना चाह सकते हैं जहाँ परिवर्तनों के बारे में सूचित करने के लिए तरीकों को ओवरराइड किया जाता है।
किरण चल्ला

84

C # में, वस्तुओं के एक बैग का प्रतिनिधित्व करने के लिए तीन अवधारणाएं हैं। बढ़ती सुविधाओं के क्रम में, वे हैं:

  • असम्भव - unordered, unmodifiable
  • संग्रह - आइटम जोड़ / निकाल सकते हैं
  • सूची - वस्तुओं को एक आदेश देने की अनुमति देता है (सूचकांक द्वारा पहुंच और हटाने)

Enumerable का कोई आदेश नहीं है। आप सेट से आइटम नहीं जोड़ सकते या निकाल नहीं सकते हैं। आप सेट में वस्तुओं की एक गिनती भी नहीं प्राप्त कर सकते हैं। यह आपको सेट में प्रत्येक आइटम को एक के बाद एक एक्सेस करने देता है।

संग्रह एक परिवर्तनीय सेट है। आप सेट से वस्तुओं को जोड़ और हटा सकते हैं, आप सेट में वस्तुओं की गिनती भी प्राप्त कर सकते हैं। लेकिन अभी भी कोई आदेश नहीं है, और क्योंकि कोई आदेश नहीं है: सूचकांक द्वारा किसी आइटम तक पहुंचने का कोई तरीका नहीं है, न ही किसी तरह का कोई तरीका है।

सूची वस्तुओं का एक निर्धारित समूह है। आप सूची को सॉर्ट कर सकते हैं, इंडेक्स द्वारा एक्सेस आइटम, इंडेक्स द्वारा आइटम हटा सकते हैं।

वास्तव में, जब इन के लिए इंटरफेस को देखते हैं, तो वे एक दूसरे पर निर्माण करते हैं:

  • interface IEnumerable<T>

    • GetEnumeration<T>
  • interface ICollection<T> : IEnumerable<T>

    • Add
    • Remove
    • Clear
    • Count
  • interface IList<T> = ICollection<T>

    • Insert
    • IndexOf
    • RemoveAt

चर, या विधि पैरामीटर की घोषणा करते समय, आपको उपयोग करने का चयन करना चाहिए

  • IEnumerable
  • ICollection
  • IList

वैचारिक रूप से आपको वस्तुओं के सेट के साथ करने की आवश्यकता है।

यदि आपको किसी सूची में प्रत्येक वस्तु के लिए कुछ करने में सक्षम होने की आवश्यकता है, तो आपको केवल आवश्यकता है IEnumerable:

void SaveEveryUser(IEnumerable<User> users)
{
    for User u in users
      ...
}

आप परवाह नहीं उपयोगकर्ता एक में रखा जाता है, तो है List<T>, Collection<T>, Array<T>या कुछ और। आपको केवल IEnumerable<T>इंटरफ़ेस की आवश्यकता है।

यदि आपको एक सेट में वस्तुओं को जोड़ने, हटाने या गिनने में सक्षम होने की आवश्यकता है, तो एक संग्रह का उपयोग करें :

ICollection<User> users = new Collection<User>();
users.Add(new User());

यदि आप एक क्रम के बारे में परवाह करते हैं, और आदेश को सही होने की आवश्यकता है, तो एक सूची का उपयोग करें :

IList<User> users = FetchUsers(db);

चार्ट के रूप में:

| Feature                | IEnumerable<T> | ICollection<T> | IList<T> |
|------------------------|----------------|----------------|----------|
| Enumerating items      | X              | X              | X        |
|                        |                |                |          |
| Adding items           |                | X              | X        |
| Removing items         |                | X              | X        |
| Count of items         |                | X              | X        |
|                        |                |                |          |
| Accessing by index     |                |                | X        |
| Removing by indexx     |                |                | X        |
| Getting index of item  |                |                | X        |

List<T>और Collection<T>में System.Collections.Genericदो वर्गों है कि इन इंटरफेस को लागू कर रहे हैं; लेकिन वे केवल वर्ग नहीं हैं:

  • ConcurrentBag<T>वस्तुओं का एक ऑर्डर किया गया बैग है ( IEnumerable<T>)
  • LinkedList<T>एक बैग है जहाँ आपको अनुक्रमणिका द्वारा वस्तुओं तक पहुँचने की अनुमति नहीं है ( ICollection); लेकिन आप संग्रह से आइटम को मनमाने ढंग से जोड़ और हटा सकते हैं
  • SynchronizedCollection<T> एक ऑर्डर किए गए संग्रह में, जहां आप इंडेक्स द्वारा आइटम जोड़ / हटा सकते हैं

तो आप आसानी से बदल सकते हैं:

IEnumerable<User> users = new SynchronizedCollection<User>();

SaveEveryUser(users);

tl; डॉ

  • अनगिनत - पहुंच वाली वस्तुएं, अनियंत्रित, बिना उपयोग के
  • संग्रह - संशोधित किया जा सकता है (जोड़ें, हटाएं, गिनें)
  • सूची - सूचकांक द्वारा एक्सेस कर सकते हैं

आपके लिए आवश्यक अवधारणा चुनें , फिर मिलान वर्ग का उपयोग करें।


11
ओपी ने कंक्रीट के प्रकारों के बारे में पूछा, और आपने इंटरफेस की तुलना की है। ठोस प्रकार संग्रह <T> IList <T> को लागू करता है और सूचकांक क्षमताओं तक पहुंच रखता है।
JJS

2
इसका उत्तर अच्छा है लेकिन प्रश्न से भटक गया है। संग्रह <T> और सूची <T> वर्गों के लिए अपने उत्तर को फिट न करें, यदि मेरा सवाल है तो मैं प्रश्नोत्तर से मतलब रखता हूं कि वे आपकी बात को सही ठहराते हैं। एक सामान्य प्रयोजन के उत्तर के लिए आप सही हो सकते हैं कि संग्रह का आदेश नहीं दिया गया है इसलिए कोई अनुक्रमण नहीं है, लेकिन सूची का आदेश दिया गया है ताकि एक निश्चित सूचकांक पर सम्मिलन संभव हो।
Kylo Ren

क्या होगा अगर मुझे ICollection <T> से सुविधाएँ मिलेंगी और सॉल्विंग और ऑक्युपेंसी भी मिलेगी?

2
यदि सूची का आदेश दिया गया है और संग्रह क्रमहीन है, तो यह चुनने के लिए एक नए शिक्षार्थी (जैसे मेरे) को आसानी से मार्गदर्शन करने के लिए एक विशाल कार्यात्मक अंतर होगा। लेकिन रुकिए, आप क्यों कहते हैं कि एक संग्रह का कोई आदेश नहीं है? यह IndexOf () और RemoveAt () विधि प्रदान करता है , इसलिए यह IS का आदेश है, है ना? क्या मुझसे यहां पर कुछ छूट गया?
रायलू

1
@RayLuo मैं विशेष रूप से ICollection<T>और करने के लिए बात कर रहा हूँ IList<T>। विभिन्न ठोस कार्यान्वयन अलग तरह से व्यवहार कर सकते हैं। उदाहरण के लिए यदि आप List<T>इसके IEnumerable<T>इंटरफ़ेस के माध्यम से एक्सेस करते हैं , तो आपके पास सूची में आइटम जोड़ने, हटाने, सॉर्ट करने या गिनने का कोई तरीका नहीं है।
इयान बॉयड

43

List<T>एप्लिकेशन कोड के भीतर आंतरिक उपयोग के लिए अभिप्रेत है। आपको सार्वजनिक एपीआई लिखने से बचना चाहिए जो स्वीकार या वापसी करते हैं List<T>(इसके बजाय सुपरक्लास या संग्रह इंटरफ़ेस का उपयोग करने पर विचार करें)।

Collection<T> कस्टम संग्रह के लिए एक बेस क्लास परोसता है (हालाँकि इसे सीधे इस्तेमाल किया जा सकता है)।

Collection<T>अपने कोड का उपयोग करने पर विचार करें जब तक List<T>कि आपकी विशिष्ट विशेषताएं न हों ।

उपरोक्त केवल सिफारिशें हैं।

[से लिया गया: फ्रेमवर्क डिज़ाइन दिशानिर्देश, दूसरा संस्करण]


यह ध्यान देने योग्य है कि वे प्रकार जो किसी भी प्रकार की उत्परिवर्तित वस्तुओं का उपयोग करते हैं अपने स्वयं के राज्य को एनकैप्सुलेट करने के लिए इस तरह की वस्तुओं को वापस करने से बचना चाहिए जब तक कि प्रश्न में वस्तुओं को उनके मालिक को सूचित करने का कोई साधन न हो, जब वे उत्परिवर्तित होते हैं, या लौटने वाले विधि का नाम ऑब्जेक्ट का स्पष्ट अर्थ है कि यह एक नया उदाहरण है। ध्यान दें कि उदाहरण के Dictionary<string, List<string>>लिए रिटर्न के लिए उदाहरण के लिए List<string>, ठीक है, क्योंकि शब्दकोश की स्थिति केवल उसकी सामग्री की बजाय सूचियों की पहचान को गुप्त करती है।
सुपरकाट

37

List<T>एक बहुत ही सामान्य रूप से देखा जाने वाला कंटेनर है, क्योंकि यह बहुत ही बहुमुखी है (बहुत सारी आसान विधियों जैसे Sort, Findआदि) के साथ - लेकिन कोई विस्तार बिंदु नहीं है यदि आप किसी भी व्यवहार को ओवरराइड करना चाहते हैं (उदाहरण के लिए आइटम चेक करें)।

Collection<T>किसी के आसपास एक रैपर है IList<T>(डिफ़ॉल्ट करने के लिए List<T>) - इसमें विस्तार बिंदु ( virtualविधियां) हैं, लेकिन जैसे कई समर्थन विधियां नहीं हैं Find। परोक्ष की वजह से, यह थोड़ा धीमा है List<T>, लेकिन बहुत ज्यादा नहीं है।

LINQ के साथ, अतिरिक्त तरीकों में List<T>कम महत्वपूर्ण हो, के बाद से LINQ करने वाली वस्तुओं वैसे भी उन्हें प्रदान करता है ... उदाहरण के लिए First(pred), OrderBy(...)आदि


6
संग्रह <T> में विधि की कमी है, यहां तक ​​कि Linq-to-Objects में भी।
tuinstoel

7
@tuinstoel - लेकिन इसे जोड़ना तुच्छ है।
मार्क Gravell

12

लिस्ट तेज है।

उदाहरण के लिए करें

private void button1_Click(object sender, EventArgs e)
{
  Collection<long> c = new Collection<long>();
  Stopwatch s = new Stopwatch();
  s.Start();
  for (long i = 0; i <= 10000000; i++)
  {
    c.Add(i);
  }
  s.Stop();
  MessageBox.Show("collect " + s.ElapsedMilliseconds.ToString());

  List<long> l = new List<long>();
  Stopwatch s2 = new Stopwatch();
  s2.Start();
  for (long i = 0; i <= 10000000; i++)
  {
    l.Add(i);
  }
  s2.Stop();
  MessageBox.Show("lis " + s2.ElapsedMilliseconds.ToString());


}

मेरी मशीन List<>पर लगभग दोगुना तेज है।

संपादित करें

मैं समझ नहीं पा रहा हूं कि लोग इसे क्यों कम कर रहे हैं। मेरी कार्य मशीन और मेरे होम मशीन दोनों पर सूची <> कोड 80% तेज है।


1
यह कैसे तेज है? देखो? निवेशन? निष्कासन? खोज? यह तेज क्यों है?
डग टी।

17
सूची संग्रह से टाइप करने के लिए कम पत्र है :)
RedFilter

1
संग्रह के कम तरीके हैं। इसलिए यह तेज है। QED। (मजाक करते हुए, मैं ट्रोल नहीं कर रहा हूं)
रे

2
मेरी मशीन पर इसकी कोशिश की गई और सूची लगभग 20% तेज है। यह क्यों हो सकता है पर कुछ चर्चा में दिलचस्पी होगी। हो सकता है कि मेमोरी आवंटित करने के साथ सूची बेहतर हो।
रे

10
सूची के तरीके अंतर्निहित नहीं हैं, इसलिए यह देखने के लिए चेक नहीं हैं कि क्या उन्हें विरासत में मिला है; संग्रह के तरीके अंतर्निहित हैं। इसका लाभ यह है कि आप संग्रह का उपयोग बेस क्लास से इनहेरिट करने और कस्टम कलेक्शन बनाने के लिए कर सकते हैं।
रिचर्ड गैड्सन

11

सूची एक संग्रह का प्रतिनिधित्व करती है जहां वस्तुओं का क्रम महत्वपूर्ण है। यह भी एक सॉर्ट और खोज के तरीकों का समर्थन करता है। संग्रह एक अधिक सामान्य डेटा-संरचना है जो डेटा के बारे में कम धारणा बनाता है और इसे हेरफेर करने के लिए कम तरीकों का भी समर्थन करता है। यदि आप एक कस्टम डेटा संरचना को उजागर करना चाहते हैं, तो आपको संभवतः संग्रह का विस्तार करना चाहिए। यदि आपको डेटा-संरचना को उजागर करने वाले डेटा w / o में हेरफेर करने की आवश्यकता है, तो एक सूची संभवतः जाने का सबसे सुविधाजनक तरीका है।


4

यह उन ग्रेड स्कूल के सवालों में से एक है। टी का एक संग्रह सार की तरह है; एक डिफ़ॉल्ट कार्यान्वयन हो सकता है (मैं एक .net / c # आदमी नहीं हूं), लेकिन एक संग्रह में बुनियादी ऑपरेशन होंगे जैसे ऐड, रिमूव, इट्रेट, और इसी तरह।

टी की सूची से इन कार्यों के बारे में कुछ बारीकियों के बारे में पता चलता है: ऐड को निरंतर समय लेना चाहिए, तत्वों की संख्या के लिए आनुपातिक समय निकालना चाहिए, गेटफैस्ट कंसेंट टाइम होना चाहिए। सामान्य तौर पर, एक सूची संग्रह का एक प्रकार है, लेकिन एक संग्रह आवश्यक रूप से एक प्रकार की सूची नहीं है।


4

हंसेलमैन बोलता है : " Collection<T>एक सूची की तरह दिखता है, और इसमें एक List<T>आंतरिक रूप से भी है । हर एक विधि आंतरिक को दर्शाता है List<T>। इसमें एक संरक्षित संपत्ति शामिल है जो उजागर करती है List<T>।"

संपादित करें: Collection<T>System.Generic.Collections .NET 3.5 में मौजूद नहीं है। यदि आप .NET 2.0 से 3.5 पर माइग्रेट करते हैं, तो यदि आप बहुत अधिक उपयोग कर रहे हैं, तो आपको कुछ कोड बदलने की आवश्यकता होगीCollection<T> वस्तुओं हैं, जब तक कि मैं कुछ स्पष्ट याद नहीं कर रहा हूं ...

EDIT 2: Collection<T>अब .NET 3.5 में System.Collections.ObjectModel नाम स्थान पर है। मदद फ़ाइल यह कहती है:

"System.Collections.ObjectModel नामस्थान में ऐसी कक्षाएं होती हैं जिन्हें पुन: प्रयोज्य लाइब्रेरी के ऑब्जेक्ट मॉडल में संग्रह के रूप में उपयोग किया जा सकता है। इन वर्गों का उपयोग तब करें जब गुण या विधियाँ संग्रह लौटा दें।"


4

इन सभी इंटरफेस से विरासत मिलती है IEnumerable, जिसे आपको सुनिश्चित करना चाहिए कि आप समझ सकें। वह इंटरफ़ेस मूल रूप से आपको फ़ॉर्च स्टेटमेंट (C # में) क्लास का उपयोग करने देता है।

  • ICollectionआपके द्वारा सूचीबद्ध इंटरफेस का सबसे बुनियादी है। यह एक गूढ़ इंटरफ़ेस है जो समर्थन करता है Countऔर इसके बारे में है।
  • IListवह सब कुछ है जो ICollectionवस्तुओं को जोड़ने और हटाने का समर्थन करता है, सूचकांक द्वारा वस्तुओं को पुनः प्राप्त करना, आदि। यह "वस्तुओं की सूचियों" के लिए सबसे अधिक उपयोग किया जाने वाला इंटरफ़ेस है, जो कि मुझे पता है कि अस्पष्ट है।
  • IQueryableएक गणनीय इंटरफ़ेस है जो LINQ का समर्थन करता है। आप हमेशा IQueryableएक IList से बना सकते हैं और LINQ का उपयोग ऑब्जेक्ट्स के लिए कर सकते हैं, लेकिन आप IQueryableLINQ में SQL स्टेटमेंट्स में SQL स्टेटमेंट्स और एंटिटीज के लिए आस्थगित निष्पादन के लिए भी उपयोग किया जाता है।
  • IDictionaryइस अर्थ में एक अलग जानवर है कि यह मूल्यों के लिए अद्वितीय कुंजी का मानचित्रण है। यह भी उल्लेखनीय है कि आप कुंजी / मान युग्मों की गणना कर सकते हैं, लेकिन अन्यथा यह आपके द्वारा सूचीबद्ध अन्य लोगों की तुलना में एक अलग उद्देश्य प्रदान करता है।

ICollection जोड़ने / हटाने / समाशोधन का समर्थन करता है: msdn.microsoft.com/en-us/library/…
amnesia

4

MSDN के अनुसार, सूची (T की) .dd "O (n) ऑपरेशन" (जब "क्षमता" पार हो जाती है), जबकि Collection (T का) .Add हमेशा "O (1) ऑपरेशन" होता है। यह समझ में आता है अगर सूची एक ऐरे और संग्रहित लिंक का उपयोग करके कार्यान्वित की जाती है। हालाँकि, अगर ऐसा होता, तो एक संग्रह (T) की अपेक्षा करता। यह "O (n) ऑपरेशन" होगा। लेकिन - यह है - नहीं !? संग्रह (टी का)। यह "ओ (1) ऑपरेशन है" जैसे सूची (टी का)। इटेम।

उस के शीर्ष पर, "tuinstoel" का "Dec 29 '08 22:31 पर" पोस्ट से ऊपर का दावा है कि गति परीक्षण दिखाता है सूची (T का)। संग्रह (T का) की तुलना में तेज़ होना है। ठीक है, जो मैंने पुन: प्रस्तुत किया है। लंबे और स्ट्रिंग का। हालाँकि मैं केवल ~ 33% तेजी से बनाम उसका दावा किया 80%, MSDN के अनुसार, यह विपरीत और "कई बार" होना चाहिए था !?


3

दोनों एक ही इंटरफेस लागू करते हैं, इसलिए वे एक ही तरह से व्यवहार करेंगे। शायद उन्हें आंतरिक रूप से अलग तरीके से लागू किया जाता है, लेकिन इसका परीक्षण करना होगा।

केवल वास्तविक अंतर जो मैं देख रहा हूं वे नामस्थान और तथ्य हैं Collection<T>, जिनके साथ चिह्नित है ComVisibleAttribute(false), इसलिए COM कोड इसका उपयोग नहीं कर सकता है।


वे अलग-अलग इंटरफेस लागू करते हैं - सूची <टी> आईलिस्ट <टी> लागू करता है, जहां संग्रह <टी> नहीं करता है।
बेवन

@ बेवन ने इसे c # में आज़माया, वे दोनों एक ही सेट के इंटरफेस को लागू करते हैं
Kylo Ren

1
यह एक दिलचस्प बदलाव है @KyloRen - वे अब दोनों इंटरफेस के एक ही सेट को लागू करते हैं; यह '08 में वापस मामला नहीं था।
बेवन

1
@ बावन दिलचस्प। सुनिश्चित नहीं हैं कि दो अलग-अलग वर्गों का कारण क्या था, सिर्फ कुछ अतिरिक्त तरीकों के साथ।
Kylo Ren

3

अन्य asnwers के अलावा, मैंने सामान्य सूची और संग्रह क्षमताओं का त्वरित अवलोकन संकलित किया है। संग्रह सूची का सीमित सबसेट है:

* =  वर्तमान
ओ = आंशिक रूप से मौजूद है

संपत्ति / विधि संग्रह < T > सूची < T > --------------------------------------- -------      

Add()                *              *
AddRange()                          *
AsReadOnly()                        *
BinarySearch()                      *
Capacity                            *
Clear()              *              *
Contains()           *              *
ConvertAll()                        *
CopyTo()             o              *
Count                *              *
Equals()             *              *
Exists()                            *
Find()                              *
FindAll()                           *
FindIndex()                         *
FindLast()                          *
FindLastIndex()                     *
ForEach()                           *
GetEnumerator()      *              *
GetHashCode()        *              *
GetRange()                          *
GetType()            *              *
IndexOf()            o              *
Insert()             *              *
InsertRange()                       *
Item()               *              *
LastIndexOf()                       *
New()                o              *
ReferenceEquals()    *              *
Remove()             *              *
RemoveAll()                         *
RemoveAt()           *              *
RemoveRange()                       *
Reverse()                           *
Sort()                              *
ToArray()                           *
ToString()           *              *
TrimExcess()                        *
TrueForAll()                        *
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.