कैसे लागू होती हैं जेनरिक?


16

यह कंपाइलर इंटर्न के दृष्टिकोण से प्रश्न है।

मुझे जेनेरिक में दिलचस्पी है, टेम्पलेट (सी ++) में नहीं, इसलिए मैंने सी # के साथ प्रश्न को चिह्नित किया। जावा नहीं, क्योंकि दोनों भाषाओं में AFAIK कार्यान्वयन में भिन्न हैं।

जब मैं w / o जेनेरिक भाषाओं को देखता हूं तो यह बहुत सीधा है, आप वर्ग की परिभाषा को मान्य कर सकते हैं, इसे पदानुक्रम में जोड़ सकते हैं और यही है।

लेकिन सामान्य वर्ग के साथ क्या करना है, और इससे भी महत्वपूर्ण बात यह है कि इसके संदर्भ कैसे संभालें? यह सुनिश्चित करने के लिए कि स्थिर क्षेत्र एकवचन के प्रति एकवचन हैं (अर्थात हर बार सामान्य पैरामीटर हल किए जाते हैं)।

मान लीजिए कि मैं एक कॉल देखता हूं:

var x = new Foo<Bar>();

क्या मुझे Foo_Barपदानुक्रम में नई कक्षा जोड़नी है?


अद्यतन: अब तक मुझे केवल 2 प्रासंगिक पोस्ट मिले, हालांकि वे इस अर्थ में अधिक विवरण में नहीं जाते हैं "यह अपने आप से कैसे करें"


Upvoting क्योंकि मुझे लगता है कि एक पूर्ण उत्तर दिलचस्प होगा। मेरे पास कुछ विचार हैं कि यह कैसे काम करता है लेकिन सही जवाब देने के लिए पर्याप्त नहीं है। मुझे नहीं लगता कि सी # में जेनरिक प्रत्येक सामान्य प्रकार के लिए विशेष कक्षाओं के लिए संकलन करता है। वे रनटाइम पर हल होने लगते हैं (जेनरिक का उपयोग करने से ध्यान देने योग्य गति हो सकती है)। शायद हम एरिक लिपर्ट को झंकार करने के लिए मिल सकते हैं?
KChaloux

2
@ केचलौक्स: एमएसआईएल स्तर पर, जेनेरिक का एक वर्णन है। जब जेआईटी चलता है, तो यह सामान्य मानदंड के रूप में उपयोग किए जाने वाले प्रत्येक मूल्य प्रकार के लिए अलग मशीन कोड बनाता है, और मशीन कोड का एक और सेट जो सभी संदर्भ प्रकारों को कवर करता है। MSIL में सामान्य विवरण को संरक्षित करना वास्तव में अच्छा है क्योंकि यह आपको रनटाइम में नए उदाहरण बनाने की अनुमति देता है।
बेन वोइग्ट

@ इसीलिए मैंने वास्तव में इस प्रश्न का उत्तर देने का प्रयास नहीं किया: p
KChaloux

मुझे यकीन है कि अगर आप अभी भी आस-पास हैं नहीं कर रहा हूँ, लेकिन आप किस भाषा का संकलन कर रहे हैं करने के लिए । आप जेनरिक को कैसे लागू करते हैं, इस पर बहुत अधिक प्रभाव पड़ेगा। मैं इस बारे में जानकारी प्रदान कर सकता हूं कि मैंने आमतौर पर सामने के छोर पर कैसे संपर्क किया है, लेकिन पीछे का अंत बेतहाशा भिन्न हो सकता है।
तेलस्टीन

@Telastyn, उन विषयों के लिए सुनिश्चित करें कि मैं :-) हूं, मैं वास्तव में C # के करीब कुछ ढूंढ रहा हूं, मेरे मामले में मैं PHP (कोई मजाक नहीं) का संकलन कर रहा हूं । यदि आप अपना ज्ञान साझा करते हैं तो मैं आपका आभारी रहूंगा।
ग्रीनोल्डमैन

जवाबों:


4

यह सुनिश्चित करने के लिए कि स्थिर क्षेत्र एकवचन के प्रति एकवचन हैं (अर्थात हर बार सामान्य पैरामीटर हल किए जाते हैं)।

प्रत्येक सामान्य तात्कालिकता की अपनी प्रति (भ्रामक रूप से नामित) मेथडटेबल है, जहां स्थिर क्षेत्र संग्रहीत हैं।

मान लीजिए कि मैं एक कॉल देखता हूं:

var x = new Foo<Bar>();

क्या मुझे Foo_Barपदानुक्रम में नई कक्षा जोड़नी है?

मुझे यकीन नहीं है कि वर्ग पदानुक्रम के बारे में सोचना उपयोगी है क्योंकि कुछ संरचना जो वास्तव में रनटाइम पर मौजूद है, यह एक तार्किक निर्माण से अधिक है।

लेकिन अगर आप मेथडबल को मानते हैं, तो प्रत्येक अपने बेस क्लास के लिए एक अप्रत्यक्ष पॉइंटर के साथ, इस पदानुक्रम को बनाने के लिए, फिर हाँ, यह पदानुक्रम में नई कक्षा जोड़ता है।


धन्यवाद, वह दिलचस्प कृति है। तो स्थिर फ़ील्ड को वर्चुअल टेबल के समान हल किया जाता है, है ना? "वैश्विक" शब्दकोश का एक संदर्भ है जो प्रत्येक प्रकार की प्रविष्टियाँ रखता है? इसलिए मैं 2 विधानसभाओं का उपयोग करके एक दूसरे के बारे में नहीं जान सकता था Foo<string>और वे स्थैतिक क्षेत्र के दो उदाहरण उत्पन्न नहीं करेंगे Foo
ग्रीनल्डमैन

1
@ग्रीनॉल्डमैन खैर, वर्चुअल टेबल के समान नहीं, बिल्कुल वैसा ही। मेथडटेबल वर्चुअल डिस्पैच में इस्तेमाल होने वाले प्रकार के स्टैटिक फील्ड और रेफरेंस के तरीकों को संदर्भित करता है (इसीलिए इसे मेथडेबल कहा जाता है)। और हाँ, CLR के पास कुछ सारणी होनी चाहिए जिसका उपयोग सभी MethodTables को एक्सेस करने के लिए कर सकते हैं।
svick

2

मुझे वहां दो वास्तविक ठोस प्रश्न दिखाई देते हैं। आप शायद पूरी तरह से समझने के लिए अतिरिक्त संबंधित प्रश्न पूछना चाहते हैं (लिंक के साथ अलग प्रश्न)।

स्थिर क्षेत्रों को सामान्य उदाहरण के अनुसार अलग-अलग उदाहरण कैसे दिए जाते हैं?

वैसे, स्थैतिक सदस्यों के लिए जो सामान्य प्रकार के मापदंडों से संबंधित नहीं हैं, यह बहुत आसान है (सामान्य पैरामीटर से मूल्य के लिए एक शब्दकोश मैप का उपयोग करें)।

सदस्य (स्थिर या नहीं) जो प्रकार के मापदंडों से संबंधित हैं, उन्हें प्रकार के क्षरण के माध्यम से नियंत्रित किया जा सकता है। बस जो भी सबसे मजबूत बाधा है (अक्सर System.Object) का उपयोग करें। क्योंकि कंपाइलर प्रकार की जाँच के बाद टाइप की जानकारी मिटा दी जाती है, इसका मतलब है कि रनटाइम प्रकार की जाँच की आवश्यकता नहीं होगी (हालाँकि इंटरफ़ेस कास्ट अभी भी रनटाइम में मौजूद हो सकता है)।

क्या प्रत्येक सामान्य उदाहरण अलग पदानुक्रम में अलग-अलग दिखाई देता है?

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

यह शायद एक अच्छा निर्णय था, क्योंकि आधार वर्ग से नामों को देखने में विफलता अविश्वसनीय रूप से आश्चर्यजनक होगी।


मेरी समस्या यह है कि मैं टेम्पलेट के संदर्भ में सोच से दूर नहीं हो सकता। उदाहरण के लिए - विपरीत टेम्पलेट सामान्य वर्ग है पूरी तरह से संकलित। इसका मतलब यह है कि अन्य विधानसभा में इस वर्ग का उपयोग करके क्या होता है? पहले से संकलित विधि को आंतरिक कास्टिंग के साथ कहा जाता है? मुझे शक है जेनरिक बाधा पर भरोसा कर सकते हैं - बल्कि तर्क पर, नहीं तो Foo<int>और Foo<string>साथ ही डेटा पर मारते थे Foow / ओ की कमी।
ग्रीनोल्डमैन

1
@ग्रीनॉल्डमैन: क्या हम एक मिनट के लिए मूल्य प्रकारों से बच सकते हैं, क्योंकि वे वास्तव में विशेष रूप से नियंत्रित होते हैं? यदि आपके पास है List<string>और List<Form>तब से, List<T>आंतरिक रूप से प्रकार का सदस्य है T[]और कोई बाधा नहीं है T, तो आपको जो वास्तव में मिलेगा वह मशीन कोड है जो एक हेरफेर करता है object[]। हालांकि, चूंकि केवल Tउदाहरणों को सरणी में रखा जाता है, इसलिए बाहर आने वाली हर चीज Tको एक अतिरिक्त प्रकार की जांच के बिना वापस किया जा सकता है । दूसरी ओर, यदि आपके पास होता ControlCollection<T> where T : Control, तो आंतरिक व्यूह T[]बन जाता Control[]
बेन वोइग्ट

क्या मैं सही ढंग से समझता हूं, कि बाधा को आंतरिक टाइपनेम के रूप में लिया जाता है और उपयोग किया जाता है, लेकिन जब वर्ग वास्तव में उपयोग किया जाता है तो कास्टिंग का उपयोग किया जाता है? ठीक है, मैं उस मॉडल को समझता हूं, लेकिन मैं इस धारणा के तहत था कि जावा इसका उपयोग करता है, सी # नहीं।
ग्रीनोल्डमैन

3
@ग्रीनॉल्डमैन: जावा स्रोत-> बायटेकोड ट्रांसलेशन स्टेप में टाइप इरेज़र करता है। जिससे वेरिफिक के लिए जेनेरिक कोड को सत्यापित करना असंभव हो जाता है। C # इसे bytecode-> मशीन कोड स्टेप में करता है।
बेन वोइगट

@BenVoigt जेनेरिक प्रकारों के बारे में कुछ जानकारी जावा में रखी गई है, अन्यथा आप इसके स्रोत के बिना जेनेरिक-उपयोग करने वाले वर्ग के खिलाफ संकलन नहीं कर सकते। यह सिर्फ बायोटेक अनुक्रम में ही नहीं रखा गया है AIUI, बल्कि क्लास मेटाडेटा में।
डोनाल्ड फेलो

1

लेकिन सामान्य वर्ग के साथ क्या करना है, और इससे भी महत्वपूर्ण बात यह है कि इसके संदर्भ कैसे संभालें?

संकलक के सामने के छोर में सामान्य तरीका दो प्रकार के उदाहरण हैं, जेनेरिक प्रकार ( List<T>) और एक बाउंड जेनेरिक प्रकार ( List<Foo>)। जेनेरिक प्रकार परिभाषित करता है कि क्या कार्य मौजूद हैं, क्या फ़ील्ड्स हैं, और जहाँ भी जेनेरिक प्रकार के संदर्भ Tउपयोग किए जाते हैं। बाध्य जेनेरिक प्रकार में जेनेरिक प्रकार का संदर्भ होता है, और प्रकार तर्क का एक सेट होता है। आपके पास तब एक ठोस प्रकार उत्पन्न करने के लिए पर्याप्त जानकारी होती है, जो सामान्य प्रकार के संदर्भों की जगह लेती है Fooया जो भी प्रकार के तर्क होते हैं। इस प्रकार का अंतर तब महत्वपूर्ण है जब आप टाइप इनफ़ॉर्मेशन कर रहे हैं और List<T>बनाम का अनुमान लगाने की आवश्यकता है List<Foo>

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

पीछे के अंत के लिए, मैं वास्तव में नहीं जानता। जेनरिक के साथ मेरे सभी कामों ने सीआईएल को बैकेंड के रूप में लक्षित किया है, इसलिए मैं उन्हें वहां समर्थित जेनरिक में संकलित कर सकता हूं।


बहुत-बहुत धन्यवाद (अफ़सोस कि मैं कई बार जवाब नहीं दे पाया)। यह सुनकर बहुत अच्छा लगा कि मैंने उस कदम को बहुत सही ढंग से निभाया - मेरे मामले List<T>में वास्तविक प्रकार (इसकी परिभाषा) रखती है, जबकि List<Foo>(मेरे दृष्टिकोण के साथ-साथ शब्दावली के लिए धन्यवाद) मेरे दृष्टिकोण की घोषणाओं को रखती है List<T>(बेशक अब बाध्य है) Fooके बजाय T)।
ग्रीनोल्डमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.