2015-11-10 4 views
5

IList, IEnumerable और ICollection के लिए source code में उपलब्ध कराई गई टिप्पणियों का कहना हैआईएलआईस्ट <T>, आईनेमरेबल <T> और आईसीओलेक्शन <T> के लिए TypeDependencyAttribute ("System.SZArrayHelper") का उद्देश्य?

ध्यान दें कि T[] : IList<T>, और हम यह सुनिश्चित करने के लिए यदि आप IList<YourValueType> उपयोग करें, हम यह सुनिश्चित करें कि एक YourValueType[] jitting बिना इस्तेमाल किया जा सकता चाहते हैं। इसलिए TypeDependencyAttributeSZArrayHelper पर। यह आंतरिक रूप से एक विशेष हैक हालांकि - VM \ compile.cpp देखें।

IList<T>SZArrayHelper पर निर्भरता क्यों है? मैं समझता हूं कि SZArrayHelper एक सरणी के चारों ओर एक सीएलआर रैपर है जो IList<T> इंटरफ़ेस लागू करता है लेकिन मुझे पूरी तस्वीर नहीं मिलती है कि इन दोनों को एक साथ क्यों बंधे हैं।

और यह कैसे सुनिश्चित करता है YourValueType[] बिना जिंग किए इस्तेमाल किया जा सकता है।

+0

शायद :) नहीं है क्योंकि संग्रह में से 99.9% कुछ स्तर पर भंडारण के लिए एक सरणी का उपयोग करें, तो यह उस निर्भरता की आवश्यकता के लिए उचित है। क्या यह आपको कोई समस्या पैदा कर रहा है या आप सिर्फ उत्सुक हैं? –

+0

@DStandley: जिज्ञासु .. लेकिन फिर यह कैसे सुनिश्चित करता है कि आपका वैल्यू टाइप [] को बिना जिंग किए इस्तेमाल किया जा सकता है। – NullReference

+1

यह वास्तव में 'YourValueType [] '* * * के बारे में नहीं है। यह संबंधित जेनेरिक इंटरफ़ेस में डालने पर इसका उपयोग करने के बारे में है। 'int []' * वास्तव में 'IENumerable को लागू नहीं करता है। GetEnumerator' भले ही ऐसा प्रतीत होता है - वास्तविक कार्यान्वयन उस रहस्यमय 'SZArrayHelper' वर्ग में है। – Luaan

उत्तर

9

यह आपके उद्धरण में उल्लिखित जेआईटी में एक हैक है। जब वीएम को पता चलता है कि SZArrayHelper पर है, तो यह कक्षा को अलग-अलग व्यवहार करता है, जिससे अधिक कुशल कोड का उपयोग किया जा सकता है।

वीएम में प्रासंगिक कोड (ध्यान दें कि मैं एक पुराने, सार्वजनिक संस्करण यहाँ उपयोग कर रहा हूँ - नहीं वास्तविक नेट वी एम) को देखते हुए:

(IList के माध्यम से एक सरणी के लिए एक कॉल या IENumerable या ICollection) विशेष रूप से संभाला जाना है। इन इंटरफेस "जादू" हैं (ज्यादातर वजह से करने के लिए काम का संबंध सेट - वे मांग पर बनाई गई हैं आंतरिक भी शब्दार्थ हालांकि, इन स्थिर इंटरफेस कर रहे हैं।)

सरणी में .NET में एक हैक का एक सा कर रहे हैं पहले स्थान पर। जब जेनेरिक इंटरफेस जोड़े गए, तो इसने कुछ समस्या उत्पन्न की - उदाहरण के लिए, int[] एक Array है, लेकिन यह एक विशेष प्रकार और int की सरणी भी है; इसने वास्तविक सामान्य प्रकार जोड़े जाने से पहले जेने सामान्य होने की अनुमति दी।

अब, एक ठोस उदाहरण देखें। आपके पास int[] है, और आप इसे LINQ में उपयोग करना चाहते हैं। चूंकि int[] लागू करता IEnumerable<int>, यह आप बॉक्स से बाहर LINQ की पूरी शक्ति देता है, और आप कुछ इस तरह लिख सकते हैं:

var positiveNumbers = numbers.Where(i => i > 0); 

सी # की दृष्टि से, वहाँ कोई समस्या नहीं है। हालांकि, वीएम के आंतरिक भाग के बिंदु से, यह एक बड़ी समस्या है, क्योंकि int[]वास्तव मेंIEnumerable<int> लागू करें! जेनेटिक्स को .NET (और C#) में पेश करने के बाद भी, सरणी अभी भी पुराने तरीके से संभाली जाती है।

हैक उन सामान्य तरीकों को संभालने के लिए SZArrayHelper का उपयोग करना है। इसलिए, उदाहरण के लिए, WhereGetEnumerator आंतरिक रूप से IEnumerable<int> पर कॉल करता है। वीएम को पता चला है कि आप सरणी पर GetEnumerator पर कॉल करने का प्रयास कर रहे हैं, और सरणी उदाहरण पर GetEnumerator को वर्चुअल रूप से प्रेषित करने की बजाय, यह कॉल को SZArrayHelper.GetEnumerator<int>() पर रीडायरेक्ट करता है।

यह एक विशाल हैक है - अगर आप SZArrayHelper के लिए संदर्भ कोड को देखो, तुम चेतावनियों के टन मिल जाएगा - उदाहरण के लिए, GetEnumerator<int> विधि एक उदाहरण विधि है, लेकिन यह this तर्क वास्तव में सरणी है (उदाहरण के लिए int[]), SZArrayHelper नहीं।

लेकिन यह हमें सरणियों के इलाज के लिए के रूप में यदि वे वास्तव में उन सभी सामान्य इंटरफेस को लागू किया था की अनुमति देता है - भले ही वे

+0

शानदार !!! इस तरह से कभी नहीं। – NullReference

संबंधित मुद्दे