हंस के जवाब के आलोक में नया उत्तर
हंस द्वारा दिए गए उत्तर के लिए धन्यवाद, हम देख सकते हैं कि कार्यान्वयन कुछ अधिक जटिल है जितना हम सोच सकते हैं। कंपाइलर और सीएलआर दोनों ही यह धारणा देने की बहुत कोशिश करते हैं कि एक सरणी प्रकार लागू होता है IList<T>
- लेकिन सरणी विचरण इस चाल को बनाता है। हंस के उत्तर के विपरीत, सरणी प्रकार (एकल-आयामी, शून्य-आधारित वैसे भी) सामान्य संग्रह को सीधे लागू करते हैं, क्योंकि किसी भी विशिष्ट सरणी का प्रकार नहीं हैSystem.Array
- यह केवल सरणी का आधार प्रकार है। यदि आप किसी सरणी प्रकार से पूछते हैं कि यह किस इंटरफेस का समर्थन करता है, तो इसमें सामान्य प्रकार शामिल हैं:
foreach (var type in typeof(int[]).GetInterfaces())
{
Console.WriteLine(type);
}
आउटपुट:
System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]
एकल-आयामी, शून्य-आधारित सरणियों के लिए, जहां तक भाषा का संबंध है, सरणी वास्तव में लागू होती IList<T>
है। C # विनिर्देश की धारा 12.1.2 ऐसा कहती है। इसलिए जो कुछ भी अंतर्निहित कार्यान्वयन करता है, भाषा को उस तरह का व्यवहार करना पड़ता है जैसे किसी अन्य इंटरफ़ेस के साथ T[]
लागू होता IList<T>
है। इस दृष्टिकोण से, इंटरफ़ेस को कुछ सदस्यों द्वारा स्पष्ट रूप से लागू किया गया है (जैसे कि Count
)। जो हो रहा है, उसके लिए भाषा के स्तर पर यह सबसे अच्छा स्पष्टीकरण है ।
ध्यान दें कि यह केवल एकल-आयामी सरणियों (और शून्य-आधारित सरणियों के लिए है, न कि C # जैसा कि एक भाषा गैर-शून्य-आधारित सरणियों के बारे में कुछ भी कहती है)। लागू T[,]
नहीं करता है IList<T>
।
सीएलआर के नजरिए से, कुछ फनीयर चल रहा है। आप सामान्य इंटरफ़ेस प्रकारों के लिए इंटरफ़ेस मैपिंग प्राप्त नहीं कर सकते। उदाहरण के लिए:
typeof(int[]).GetInterfaceMap(typeof(ICollection<int>))
इसका एक अपवाद देता है:
Unhandled Exception: System.ArgumentException: Interface maps for generic
interfaces on arrays cannot be retrived.
तो विचित्रता क्यों? खैर, मुझे विश्वास है कि यह वास्तव में सरणी कोवरियन के कारण है, जो कि टाइप सिस्टम में एक मस्सा है, IMO। भले ही IList<T>
है नहीं (और सुरक्षित रूप से नहीं किया जा सकता) covariant, सरणी सहप्रसरण काम करने के लिए इस अनुमति देता है:
string[] strings = { "a", "b", "c" };
IList<object> objects = strings;
... जो इसे लागू करने की तरह दिखताtypeof(string[])
है IList<object>
, जब यह वास्तव में नहीं होता है।
CLI कल्पना (ECMA-335) विभाजन 1, खंड 8.7.1, में यह है:
एक हस्ताक्षर प्रकार टी संगत है-एक हस्ताक्षर प्रकार यू के साथ और यदि केवल निम्न में से कम से कम एक धारण करता है
...
टी एक शून्य-आधारित रैंक -1 सरणी है V[]
, और U
है IList<W>
, और वी सरणी-तत्व-संगत-डब्ल्यू के साथ है।
(यह वास्तव में उल्लेख नहीं करता है ICollection<W>
या IEnumerable<W>
जो मुझे लगता है कि कल्पना में एक बग है।)
गैर-विचरण के लिए, CLI युक्ति सीधे भाषा युक्ति के साथ जाती है। विभाजन 1 की धारा 8.9.1 से:
इसके अतिरिक्त, तत्व प्रकार T के साथ एक निर्मित वेक्टर, इंटरफ़ेस को लागू करता है System.Collections.Generic.IList<U>
, जहां U: = T. (.78.7)
(एक वेक्टर एक शून्य-आधार वाला एकल-आयामी सरणी है।)
अब के मामले में कार्यान्वयन विवरण , स्पष्ट रूप से CLR कुछ अजीब मानचित्रण काम अनुकूलता यहाँ रखने के लिए कर रही है: जब एक string[]
के कार्यान्वयन के लिए कहा जाता है ICollection<object>.Count
, यह उस में नहीं संभाल सकता है काफी सामान्य तरीके से। क्या यह स्पष्ट इंटरफ़ेस कार्यान्वयन के रूप में गिना जाता है? मुझे लगता है कि इस तरह से व्यवहार करना उचित है, जब तक कि आप सीधे इंटरफ़ेस मैपिंग के लिए नहीं पूछते हैं, यह हमेशा भाषा के दृष्टिकोण से उस तरह का व्यवहार करता है।
किस बारे में ICollection.Count
?
अब तक मैंने जेनेरिक इंटरफेस के बारे में बात की है, लेकिन फिर ICollection
इसकी Count
संपत्ति के साथ गैर-जेनेरिक है । इस बार हम इंटरफ़ेस मैपिंग प्राप्त कर सकते हैं, और वास्तव में इंटरफ़ेस सीधे द्वारा कार्यान्वित किया जाता है System.Array
। ICollection.Count
संपत्ति के कार्यान्वयन के लिए दस्तावेज Array
जो स्पष्ट इंटरफ़ेस कार्यान्वयन के साथ लागू होता है।
अगर कोई इस तरह के स्पष्ट इंटरफ़ेस कार्यान्वयन के बारे में सोच सकता है जो "सामान्य" स्पष्ट इंटरफ़ेस कार्यान्वयन से अलग है, तो मैं इसे आगे देखने के लिए खुश हूं।
स्पष्ट इंटरफ़ेस कार्यान्वयन के आसपास पुराना उत्तर
उपरोक्त के बावजूद, जो सरणियों के ज्ञान के कारण अधिक जटिल है, आप अभी भी स्पष्ट इंटरफ़ेस कार्यान्वयन के माध्यम से समान दृश्य प्रभावों के साथ कुछ कर सकते हैं ।
यहाँ एक सरल स्टैंडअलोन उदाहरण दिया गया है:
public interface IFoo
{
void M1();
void M2();
}
public class Foo : IFoo
{
// Explicit interface implementation
void IFoo.M1() {}
// Implicit interface implementation
public void M2() {}
}
class Test
{
static void Main()
{
Foo foo = new Foo();
foo.M1(); // Compile-time failure
foo.M2(); // Fine
IFoo ifoo = foo;
ifoo.M1(); // Fine
ifoo.M2(); // Fine
}
}
Array
क्लास को C # लिखा जाना था!