इससे पहले कि मैं भी पूछते हैं, मुझे रास्ते से हट स्पष्ट जवाब मिलता है: ICollection<T>
इंटरफ़ेस एक मनमाना तत्व दूर करने के लिए है, जो Queue<T>
और Stack<T>
वास्तव में (समर्थन नहीं कर सकते हैं क्योंकि वे केवल "अंत" निकाल सकते हैं एक Remove
विधि शामिल तत्व)।क्यूई (टी) और स्टैक (टी) क्यों आईसीओलेक्शन (टी) लागू नहीं करते हैं?
ठीक है, मुझे एहसास है। असल में, मेरा प्रश्न विशेष रूप से Queue<T>
या Stack<T>
संग्रह प्रकारों के बारे में नहीं है; बल्कि, जेनेरिक प्रकार के लिए T
मानों का संग्रह अनिवार्य रूप से ICollection<T>
लागू करने के डिजाइन निर्णय के बारे में है।
यहां मुझे अजीब लगता है। मान लें कि मेरे पास एक विधि है जो T
के मनमानी संग्रह को स्वीकार करती है, और जिस कोड को मैं लिख रहा हूं उसके उद्देश्य के लिए संग्रह के आकार को जानना उपयोगी होगा। उदाहरण के लिए (नीचे दिए गए कोड उदाहरण के लिए ही तुच्छ है,!):
// Argument validation omitted for brevity.
static IEnumerable<T> FirstHalf<T>(this ICollection<T> source)
{
int i = 0;
foreach (T item in source)
{
yield return item;
if ((++i) >= (source.Count/2))
{
break;
}
}
}
अब, वहाँ वास्तव में कोई कारण नहीं क्यों इस कोड को एक Queue<T>
या एक Stack<T>
पर काम नहीं कर सकता है, सिवाय इसके कि उन प्रकार को लागू नहीं करते ICollection<T>
। वेICollection
लागू जाहिर है-मैं Count
संपत्ति के लिए मुख्य रूप से अनुमान लगा कर अकेले-लेकिन यह है कि इस तरह अजीब अनुकूलन कोड की ओर जाता है:
// OK, so to accommodate those bastard Queue<T> and Stack<T> types,
// we will just accept any IEnumerable<T>...
static IEnumerable<T> FirstHalf<T>(this IEnumerable<T> source)
{
int count = CountQuickly<T>(source);
/* ... */
}
// Then, assuming we've got a collection type with a Count property,
// we'll use that...
static int CountQuickly<T>(IEnumerable collection)
{
// Note: I realize this is basically what Enumerable.Count already does
// (minus the exception); I am just including it for clarity.
var genericColl = collection as ICollection<T>;
if (genericColl != null)
{
return genericColl.Count;
}
var nonGenericColl = collection as ICollection;
if (nonGenericColl != null)
{
return nonGenericColl.Count;
}
// ...or else we'll just throw an exception, since this collection
// can't be counted quickly.
throw new ArgumentException("Cannot count this collection quickly!");
}
इसे और अधिक समझ बनाने के सिर्फ परित्याग करने के लिए नहीं चाहेंगे ICollection
इंटरफ़ेस पूरी तरह से (मेरा मतलब यह नहीं है कि कार्यान्वयन ड्रॉप, निश्चित रूप से, क्योंकि यह एक तोड़ने वाला परिवर्तन होगा; मेरा मतलब है, इसका उपयोग करना बंद करें), और केवल उन सदस्यों के लिए स्पष्ट कार्यान्वयन के साथ ICollection<T>
लागू करें जिनके पास सही नहीं है मेल खाते हैं?
मेरा मतलब है, क्या ICollection<T>
प्रस्तावों को देखो:
Count
-Queue<T>
औरStack<T>
दोनों इस की है।IsReadOnly
-Queue<T>
औरStack<T>
आसानी से यह हो सकता है।Add
-Queue<T>
, (Enqueue
के साथ) स्पष्ट रूप से यह लागू हो सकता है कर सकते थेStack<T>
(Push
के साथ) के रूप में।Clear
- जांचें।Contains
- जांचें।CopyTo
- जांचें।GetEnumerator
- चेक (डुह)।Remove
- यह केवल एकमात्र ऐसा है जोQueue<T>
औरStack<T>
के लिए एकदम सही मिलान नहीं है।
और यहाँ असली किकर है: ICollection<T>.Remove
रिटर्न एक bool
; इसलिए Queue<T>
के लिए एक स्पष्ट कार्यान्वयन पूरी तरह से (उदाहरण के लिए) की जांच कर सकता है, तो आइटम हटा दिया जाना चाहिए वास्तव में सिर तत्व (Peek
का उपयोग) है, और यदि हां, Dequeue
फोन और true
लौटने के लिए, अन्यथा false
लौट आते हैं। Stack<T>
को Peek
और Pop
के साथ आसानी से एक ही कार्यान्वयन दिया जा सकता है। क्यों नहीं किया Queue<T>
और Stack<T>
के डिजाइनरों इस इंटरफ़ेस को लागू:
ठीक है, अब है कि मैं क्यों मैं लगता है कि यह संभव हो जाएगा पर एक हजार शब्दों के बारे में लिखा है, मैं स्पष्ट सवाल मुद्रा ? यही है, डिजाइन कारक क्या थे (जिन्हें मैं शायद विचार नहीं कर रहा हूं) जिससे निर्णय हुआ कि यह गलत विकल्प होगा? ICollection
क्यों लागू किया गया था?
मुझे आश्चर्य है कि, मेरे अपने प्रकारों को डिजाइन करने में, क्या कोई मार्गदर्शक सिद्धांत है जो मुझे इंटरफेस कार्यान्वयन के संबंध में विचार करना चाहिए जिसे मैं इस प्रश्न पूछने में अनदेखा कर सकता हूं। उदाहरण के लिए, क्या यह केवल उन इंटरफेस को स्पष्ट रूप से कार्यान्वित करने के लिए बुरी आदत माना जाता है जो सामान्य रूप से पूरी तरह से समर्थित नहीं हैं (यदि हां, तो List<T>
IList
लागू करने के साथ ऐसा लगता है)? क्या कोई वैचारिक कतार/स्टैक की अवधारणा के बीच डिस्कनेक्ट है और ICollection<T>
का प्रतिनिधित्व करने के लिए क्या है?
मूल रूप से, मैं समझ होनी चाहिए कि एक बहुत अच्छा कारण Queue<T>
(उदाहरण के लिए) नहीं लागू ICollection<T>
, और मैं बस आँख बंद करके आगे जाने के लिए अगर कोई अनुचित सामग्री में अपने ही प्रकार के इंटरफेस डिजाइन और लागू करने नहीं करना चाहते मैं जो कुछ भी कर रहा हूं उसके माध्यम से सूचित किए बिना पूरी तरह से सोचने के तरीके।
मैं सुपर-लंबे प्रश्न के लिए क्षमा चाहता हूं।
बस एमएस के खराब संग्रह पुस्तकालयों का एक और उदाहरण। इंटरफ़ेस को केवल पढ़ने-पढ़ने और पढ़ने-लिखने वाले संस्करणों में पढ़ने के लिए कम से कम इस समस्या को हल किया जा सकता था (केवल पढ़ने-योग्य संस्करण से प्राप्त पढ़ने वाले संस्करण के साथ) और यहां तक कि बेहतर अनाज वाले इंटरफ़ेस भी होते हैं, केवल एक पर ध्यान केंद्रित करते हैं अप्रासंगिक गुणों और विधियों को शामिल करने के बजाय संग्रह का विशिष्ट पहलू। तो ICollection में शामिल, साफ़ या निकालना शामिल नहीं होना चाहिए था। यह छोड़ा जाना चाहिए था, उदाहरण के लिए, IMutableCollection । आईसीओलेक्शन अधिक कक्षाओं द्वारा कार्यान्वित किया जा सकता है। –
siride
@ साइराइड: एमएस संग्रह पुस्तकालयों का आपका विचार मेरा दर्पण करता है। यह अजीब बात है कि अनुक्रमित गुणों जैसी चीजों को केवल पढ़ने के लिए और पढ़ने-लिखने के संस्करणों के लिए दो बार परिभाषित किया जाना चाहिए, लेकिन ऐसा जीवन है।'12 निकालें 'को लागू करने के लिए नवाचार के लिए – supercat
+1, यह अच्छा था :) और नहीं, यह सुपर-लंबा क्यू अच्छी तरह लिखा गया है। – nawfal