2013-07-18 8 views
13

this स्टैक ओवरफ्लो पर उत्तर के अनुसार, सी # में जेनेरिक प्रकार रनटाइम पर हल किया गया है।सी # में सामान्य प्रकार का हल कब होता है?

हालांकि, this उत्तर के अनुसार, सी # में, जेनेरिक प्रकार संकलित समय पर हल किया गया है।

मुझे यहां क्या याद आ रही है?

दूसरे शब्दों में, T संकलन समय या रन समय पर हल किया गया है?

अद्यतन:

Oded के जवाब के आधार पर, इस तरह के मामले में, जहां प्रकार एक बंद ठोस प्रकार है (जिसका अर्थ यह संकलन समय पर हल किया जाएगा) में

class Program 
{ 
    static void Main() 
    { 
     var t = new Test<int>(); 
    } 
} 

public class Test<T> 
{ 
} 
होगा

MSIL

class Program 
{ 
    static void Main() 
    { 
     var t = new Test(); 
    } 
} 

public class Test<int> 
{   
} 
+3

आप जिन दो पोस्टों से लिंक करते हैं वे वास्तव में विभिन्न अवधारणाओं का वर्णन कर रहे हैं। – JerKimball

+2

आपके द्वारा प्रदान किए गए लिंक में पोस्ट किए गए उत्तर से इसका क्या हिस्सा आपको समझ में नहीं आता है 'नहीं; यह मूल रूप से असंभव है। जेनरिक का पूरा बिंदु यह है कि वे संकलन-समय प्रकार बनाते हैं। आप एक प्रकार का निर्माण करने की कोशिश कर रहे हैं जो संकलन समय पर अज्ञात है। हालांकि, आप इसे प्रतिबिंब का उपयोग करके कर सकते हैं। (टाइपऑफ (MyClass <>)। MakeGenericType (myType)) ' – MethodMan

+0

मुझे लगता है कि आप 'प्रतिबिंब कैसे करें' उदाहरण – MethodMan

उत्तर

21

समस्या यह है कि सवाल अच्छी तरह से तैयार नहीं है। दो लोग विपरीत चीजों का दावा कर रहे हैं: उन प्रकारों को रनटाइम पर "हल किया गया" है और संकलित समय पर उन प्रकारों को "हल" किया जाता है।

चूंकि वे एक दूसरे के विरोधाभास कर रहे हैं, इसलिए दोनों को "हल" द्वारा कुछ अलग करना चाहिए।

मुझे नहीं पता कि एक प्रकार के लिए "हल" होने का क्या अर्थ है। मुझे पता है कि ओवरलोड रिज़ॉल्यूशन है। जब एक अधिभार संकल्प समस्या यह है कि dynamic शामिल नहीं करता है का समाधान करने के लिए कहा, सी # संकलक निर्धारित करता है जो संकलन समय पर कॉल करने के लिए ओवरलोड, संकलन समय जानकारी सामान्य प्रकार के बारे में पर आधारित है। उदाहरण के लिए, यदि आपके पास:

static void Main() 
{ 
    var d = new D(); 
    var p = new P<D>(); 
    p.N(d);//Displays In class B 
} 


class B 
{ 
    public void M()// Note, not virtual 
    { 
     Console.WriteLine("In class B"); 
    } 
} 

class D : B 
{ 
    public new void M()// new, not overload 
    { 
     Console.WriteLine("In class D"); 
    } 
} 

class P<T> where T : B 
{ 
    public void N(T t) 
    { 
     t.M(); 
    } 
} 

N हमेशा B.Mकॉल भले ही P<T>P<D> के रूप में instantiated है। क्यूं कर? क्योंकि अधिभार संकल्प समस्या निर्धारित करता है कि क्या t.M का अर्थ हल किया जाना चाहिए जब P<T>.N संकलित किया गया है, और उस समय, सबसे अच्छा संकलक जानता है कि tB होना चाहिए है, इसलिए यह B.M चुनता है।

यदि यह "हल" से आपका मतलब नहीं है तो प्रश्न को स्पष्ट करें।

+0

क्या आप उदाहरण ओवरलोड रिज़ॉल्यूशन या बाइंडिंग दिखाते हैं? बाध्यकारी के लिए ओवरलोड रिज़ॉल्यूशन की आवश्यकता होती है, केवल 'एम' नाम के साथ केवल दो विधियों के समान हस्ताक्षर होते हैं, इसलिए "ओवरलोड रिज़ॉल्यूशन" के साथ काम करने के लिए केवल एक उम्मीदवार होगा। मुझे लगता है कि "ओवरलोड रिज़ॉल्यूशन" के लिए एक बेहतर उदाहरण 'स्थिर बूल (टी पी 1, टी पी 2) की तुलना करें जहां टी: कक्षा {वापसी पी 1 == पी 2;} ... तुलना करें ("5", 5. टॉस्ट्रिंग()) '। चूंकि संकलक यह नहीं जान सकता कि 'टी' प्रकार 'स्ट्रिंग' प्रकार का होगा, यह नहीं पता कि इसे संदर्भ तुलना करने के बजाय' ==' के 'स्ट्रिंग'-बनाम' स्ट्रिंग' अधिभार का उपयोग करना चाहिए? – supercat

+0

बीटीडब्ल्यू, '==' एक अधिभार की संदर्भ-तुलना है, या यह किसी अन्य प्रकार का कंपाइलर जादू है? 'ऑब्जेक्ट' प्रकार के पैरामीटर लेने वाले '==' का अधिभार किसी भी दो प्रकार की तुलना करने की अनुमति देगा, लेकिन सी # '==' ऑपरेटर इस तरह काम नहीं करता है। इसका व्यवहार सामान्य ओवरलोड रिज़ॉल्यूशन के माध्यम से हासिल की जा सकने वाली किसी भी चीज़ से काफी अलग दिखता है। – supercat

+0

@supercat: अच्छा सवाल है। यह वास्तव में कुछ छोटे संशोधनों के साथ सामान्य ऑपरेटर अधिभार रिज़ॉल्यूशन का उपयोग करता है। सबसे पहले, 'x == null',' null! = X' 'के रूप में अभिव्यक्तियों को विशेष रूप से संभाला जाता है। फिर अधिभार संकल्प सामान्य रूप से होता है। फिर एक पोस्ट-रिज़ॉल्यूशन सत्यापन चरण है। अगर ओवरलोड रिज़ॉल्यूशन 'ऑब्जेक्ट == ऑब्जेक्ट' ऑपरेटर चुनता है और एक या दोनों ऑपरेंड संदर्भ प्रकार के नहीं हैं तो त्रुटि स्थिति ट्रिगर होती है। (यह संक्षिप्त स्केच सभी subtleties का वर्णन नहीं करता है; विवरण के लिए spec देखें।) –

12

के बराबर आप open and closed generic types की अवधारणाओं याद कर रहे हैं की है।

अनिवार्य रूप से, एक बंद जेनेरिक प्रकार तब होता है जब आप वास्तव में सामान्य पैरामीटर/एस (या वे कंपाइलर द्वारा अनुमानित) पर मौजूदा प्रकार निर्दिष्ट करते हैं। उदाहरण के लिए:

Nullable<int> nulInt; 

एक खुला सामान्य प्रकार एक जहाँ एक या अधिक सामान्य प्रकार रनटाइम के दौरान निर्धारित किया जाना है है (हां, तो Nullable<T> वर्ग एक उदाहरण है)।

+0

आह, इसे दूर करें - आपने मुझे इसे हराया। :) – JerKimball

1
  1. पहले उत्तर विधि के बारे में
  2. मानकों और दूसरे सामान्य प्रकार पैरामीटर

आप यही भूल रहे है के बारे में है।

अधिक सटीक: 1. सी # स्थैतिक डिफ़ॉल्ट रूप से लिखा गया है, इसलिए जब पैरामीटर प्रदान करने के आप सबसे अच्छा फिटिंग के प्रकार और विधि मिलेगा। ("गतिशील" पैरामीटर के बारे में भी जवाब देखें।) 2. सी # सिंटैक्स द्वारा जेनेरिक टाइप पैरामीटर सेट करना स्थिर प्रकारों के बारे में है। प्रतिबिंब द्वारा इसे सेट करना कुछ और है।

कुछ और: ".NET में" प्रत्येक प्रकार के क्रम में अपना पहला उपयोग पर एक प्रारंभ चरण है। (स्थिर क्षेत्रों और स्थिर निर्माता देखें)

तो : सभी प्रकार के संकलन समय पर रनटाइम पर प्रारंभ हैं, लेकिन स्थिर प्रकार उपयोग किया जाता है (या गतिशील ...) कि है वे जब "होने की जरूरत है हल "।

1

ओपन प्रकार (myclass<T>) रन टाइम मौजूद नहीं है। लेकिन रनबाइम पर अनबाउंड प्रकार मौजूद हो सकते हैं (myclass<>)। रनटाइम पर एक अनबाउंड प्रकार को हल करने के लिए, आपको टाइपफ़ो ऑपरेटर का उपयोग करने की आवश्यकता है।

दूसरे शब्दों में, जब तक टाइपफ़ो ऑपरेटर का उपयोग नहीं किया जाता है, सामान्य प्रकार संकलन समय पर बंद होते हैं।

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