2010-05-25 16 views
6

के साथ सी # विधि पॉलीमोर्फिज्म का प्रदर्शन मैंने सी # में विपरीत सी # में देखा, आप वर्चुअल और जेनेरिक तरीकों को जोड़ सकते हैं। उदाहरण के लिए:जेनिक्स

using System.Diagnostics; 

class Base { 
    public virtual void Concrete() {Debug.WriteLine("base concrete");} 
    public virtual void Generic<T>() {Debug.WriteLine("base generic");} 
} 

class Derived : Base { 
    public override void Concrete() {Debug.WriteLine("derived concrete");} 
    public override void Generic<T>() {Debug.WriteLine("derived generic");} 
} 

class App { 
    static void Main() { 
     Base x = new Derived(); 
     x.Concrete(); 
     x.Generic<PerformanceCounter>(); 
    } 
} 

यह देखते हुए कि Generic<T> के संस्करणों के किसी भी संख्या instantiated जा सकता है, यह देखने के लिए नहीं है मानक vtbl दृष्टिकोण की तरह विधि कॉल को हल करने के लिए इस्तेमाल किया जा सकता है, और वास्तव में यह नहीं है। यहाँ उत्पन्न कोड है:

 x.Concrete(); 
mov   ecx,dword ptr [ebp-8] 
mov   eax,dword ptr [ecx] 
call  dword ptr [eax+38h] 
     x.Generic<PerformanceCounter>(); 
push  989A38h 
mov   ecx,dword ptr [ebp-8] 
mov   edx,989914h 
call  76A874F1 
mov   dword ptr [ebp-4],eax 
mov   ecx,dword ptr [ebp-8] 
call  dword ptr [ebp-4] 

अतिरिक्त कोड में बुला सामान्य मानकों के अनुसार एक गतिशील vtbl को देख जा करने के लिए, और उसके बाद दिखाई देता है। क्या किसी ने इस कार्यान्वयन के विनिर्देशों के बारे में लिखा है? गैर-सामान्य मामले की तुलना में यह कितना अच्छा प्रदर्शन करता है?

उत्तर

3

.NET जेनेरिक कार्यान्वयन आसानी से और बहुत अच्छे प्रदर्शन के साथ इस तरह के परिदृश्य को संभाल सकता है। मैंने कुछ समय पहले इसके बारे में blog post लिखा है।

सीएलआर जेनिक्स लागू करने के तरीके के बारे में जानकारी खोजने के लिए सबसे अच्छे संसाधनों में से एक है यह paper माइक्रोसॉफ्ट रिसर्च द्वारा है।

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

जबकि निष्पादन योग्य कोड (तात्कालिकता, मूल छवि) सभी सामान्य प्रकार के पैरामीटर के लिए तत्कालताओं के बीच साझा किया जाता है जो संदर्भ प्रकार हैं, तत्काल के एक उदाहरण (ऑब्जेक्ट) से जुड़े vtable कंक्रीट पैरामीटर प्रकार के लिए अद्वितीय है।

यहाँ ऊपर उल्लेख किया कागज से प्रासंगिक उद्धरण है:

4,2 CLR के कचरा-एकत्र ढेर में वस्तु प्रतिनिधित्व वस्तुओं एक vtable सूचक वस्तु की सामग्री (जैसे फाई elds या सरणी के बाद का प्रतिनिधित्व करती हैं तत्व)। vtable की मुख्य भूमिका आभासी विधि प्रेषण है: इसमें प्रत्येक विधि के लिए कोड पॉइंटर शामिल है जो ऑब्जेक्ट की कक्षा द्वारा विरासत में प्राप्त है। लेकिन सरल वर्ग प्रकारों के लिए, कम से कम जहां एक-से-एक vtables और कक्षाओं के बीच पत्राचार है, तो इसका उपयोग ऑब्जेक्ट के प्रकार का प्रतिनिधित्व करने के लिए भी किया जा सकता है। जब vtable इस तरह से उपयोग किया जाता है तो हम इसे प्रकार के प्रकार हैंडल कहते हैं।बहुरूपता के कार्यान्वयन आधारित पूर्ण विशेषज्ञता पर, सटीक रन-टाइम प्रकार की धारणा में ही पैरामिट्रीकृत प्रकार के नि: शुल्क के रूप में विभिन्न instantiations के लिए आता है अलग vtables है। लेकिन अब मान लीजिए कि कोड के बीच साझा किया गया है जैसे List<string> और List<object>। के लिए vtables दो तत्काल समान होंगे, इसलिए हमें रन-टाइम पर तत्कालता का प्रतिनिधित्व करने का कुछ तरीका चाहिए।

...

[प्रत्येक इन्स्टेन्शियशन के लिए, हम] vtable सूचक एक सूचक द्वारा एक vtable- संयुक्त और इन्स्टेन्शियशन संरचना करने के लिए बदलें और इन्स्टेन्शियशन प्रति यह [संरचना] नकल।

+0

बिल्कुल वही जो मैं खोज रहा था, धन्यवाद! – zildjohn01

0

जेनेरिक वर्ग (या विधि) के प्रत्येक उपयोग के लिए .NET जेनेरिक लागू किए जाते हैं, सीएलआर उस वर्ग (या विधि) का एक नया कार्यान्वयन बनाता है जिसमें सामान्य पैरामीटर भरा होता है। संदर्भ प्रकारों के लिए, वे सभी एक ही कार्यान्वयन साझा करें (क्योंकि वे सभी एक ही आकार के पॉइंटर्स हैं); structs प्रत्येक के अपने कार्यान्वयन के रूप में आकार सभी अलग हैं।

तो मुझे लगता है कि सामान्य प्रकार/विधि के प्रत्येक कार्यान्वयन में इसका स्वयं का vtable भी है, और वह कोड 'लुकअप जेनेरिक कार्यान्वयन' कर रहा है, फिर उसे 'कार्यान्वयन पर एक लुकअप vtable ओवरराइड' कर रहा है।

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