2012-10-24 17 views
6

मैं एक सामान्य सूची < बनाना चाहता हूं> जिसका प्रकार रनटाइम पर घोषित किया गया है।सी # गतिशील जेनेरिक सूची

मैं निम्नलिखित कर सकता हूं, लेकिन चूंकि यह गतिशील है, मुझे संदेह है कि गति गति है। मैं एक विदेशी डेटाबेस में एक रैपर लिख रहा हूं, इसलिए गति महत्वपूर्ण है।

List<dynamic> gdb = new List<dynamic>() 

मैं गतिशील सामान्य प्रकार में this post पढ़ा है, लेकिन यह काम करने के लिए नहीं मिल सकता है। विशेष रूप से, वस्तु सूची के रूप में दिखाई नहीं दे रही है और इसलिए इसमें कोई अतिरिक्त विधि नहीं है।

Type ac; 

    switch (trail[dataPos].Type) 
    { 
     case GlobalsSubscriptTypes.Int32: 
      ac = typeof(System.Int32); 

      break; 
     case GlobalsSubscriptTypes.Int64: 
      ac = typeof(System.Int64); 

      break; 

     default: 
      ac = typeof(System.String); 

      break; 
    } 

    var genericListType = typeof(List<>); 
    var specificListType = genericListType.MakeGenericType(ac); 
    var gdb = Activator.CreateInstance(specificListType); 

मैं कैसे करूँ gdb निम्न में से एक के रूप में प्रकट करने के लिए मिलता है:

List<System.Int32> 
List<System.Int64> 
List<System.String> 
+1

यह उस मामले में केवल 'सूची ' का उपयोग करना आसान हो सकता है। यदि संकलन समय पर प्रकार ज्ञात नहीं है तो संकलन समय जांचने के लिए जेनरिक आपको बताएंगे कि आपको कोई मदद नहीं होगी। – Servy

+0

कोई बुरा विचार नहीं है, लेकिन मैं चाहता हूं कि सूची टाइप की जाए क्योंकि यह एक क्वेरी का हिस्सा होगा। – IamIC

+0

सूची के बारे में कैसे? –

उत्तर

5

एक बार जब आप Activator.CreateInstance का उपयोग कर चुके हैं, तो आप परिणाम को उचित प्रकार में डाल सकते हैं। उदाहरण के लिए आप IList इस्तेमाल कर सकते हैं:

var gdb = (IList)Activator.CreateInstance(specificListType); 
gdb.Add(1); 

ध्यान दें कि ऊपर एक ArgumentException फेंकता है तो आप किस प्रकार जोड़ रहे हैं सामान्य प्रकार से मेल नहीं खाता।

+0

यह वह उत्तर है जिसे मैं ढूंढ रहा था। मैं गलत जगह पर कास्टिंग कर रहा था। – IamIC

+0

यदि आप केवल गैर-जेनेरिक इंटरफ़ेस का उपयोग करने जा रहे हैं तो आप 'सूची ' का उपयोग कर सकते हैं और सूची बनाने के लिए प्रतिबिंब का उपयोग करने की आवश्यकता को स्वयं बचा सकते हैं। – Servy

+1

@ सर्वी जो प्रत्येक int और लंबे समय तक बॉक्सिंग और अनबॉक्स किए जाने की आवश्यकता होगी, जो एक महत्वपूर्ण प्रदर्शन हिट है। – IamIC

1

आपके मामले में, gdb हमेशा एक System.Object हो जाएगा के रूप में किसी भी प्रकार की CreateInstance रिटर्न वस्तुओं,।

आपके पास कुछ विकल्प यहां है - आप IList (गैर सामान्य) के रूप में यह डाली सकता है, जैसा कि आप जानते हैं कि List<T> इस इंटरफेस को लागू करता है, और IList.Add का उपयोग करें।

वैकल्पिक रूप से, आप बस इसे dynamic घोषित कर सकता है, और बाध्यकारी गतिशील का उपयोग करें:

dynamic gdb = Activator.CreateInstance(specificListType); 

यह है कि यह उचित प्रकार का एक List<T> है आप अपने कोड लिखने दूँगी, और कॉल रनटाइम पर बाध्य होंगे गतिशील बाध्यकारी के माध्यम से।

3

ओह, gdbसही प्रकार के है। चूंकि आप रनटाइम पर टाइप निर्धारित करते हैं, इसलिए संकलक इसे नहीं जानता है। इसलिए, यह सांख्यिकीय रूप से object के रूप में टाइप किया गया है और Add विधि नहीं दिखाता है।

  1. को सही प्रकार पर कास्ट यह:

    ((System.Collections.IList) gdb).Add(...); 
    
  2. गतिशील मंगलाचरण का प्रयोग करें:

    एक आम महाप्रकार को

    switch (trail[dataPos].Type) 
    { 
        case GlobalsSubscriptTypes.Int32: 
         ((List<int>) gdb).Add(...); 
         break; 
        ... 
        default: 
         ((List<String>) gdb).Add(...); 
         break; 
    } 
    
  3. कास्ट आपके पास कुछ विकल्प है कि ठीक करने के लिए है

    dynamic gdb = Activator.CreateInstance(specificListType); 
    gdb.Add(...); 
    
1

List<dynamic>List<object> टाइप किए गए List<int> पर कोई गति दंड नहीं है, उदाहरण के लिए, मुक्केबाजी मूल्य प्रकारों से परे। हालांकि अगर आप आईएलिस्ट को डालने जा रहे हैं तो आपको अभी भी मुक्केबाजी दंड एफवाईआई होगा।

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

क्या इससे कोई फर्क पड़ता है? आप तब तक नहीं जानेंगे जब तक कि आप वास्तव में प्रोफ़ाइल चलाते हैं क्योंकि यह हमेशा आपके वास्तविक उपयोग पर निर्भर करेगा।

मेरे सबसे अच्छे अतिथि तुम सच में क्या करना चाहते हैं क्या है:

IList gdb; 

switch (trail[dataPos].Type) 
{ 
    case GlobalsSubscriptTypes.Int32: 
     gdb = new List<int>(); 
     break; 
    case GlobalsSubscriptTypes.Int64: 
     gdb = new List<long>(); 
     break; 
    default: 
     gdb = new List<string>(); 
     break; 
} 

इसके अलावा, अगर तुम सच में अपने सभी काम करने के लिए एक सामान्य सहायक विधि बनाने के मुक्केबाजी के बिना संचालन करने की जरूरत है:

switch (trail[dataPos].Type) 
{ 
    case GlobalsSubscriptTypes.Int32: 
     return Helper<int>(trail[dataPos]); 
    case GlobalsSubscriptTypes.Int64: 
     return Helper<long>(trail[dataPos]); 
    default: 
     return Helper<string>(trail[dataPos]); 
} 
+0

आपके स्पष्ट स्पष्टीकरण के लिए धन्यवाद। मुझे सहायक विचार पसंद है (हालांकि मैंने इसके कोड के बारे में बहुत कुछ नहीं सोचा है)। जैसा कि यह निकलता है, बहुरूपता के कारण मेरे पास कक्षा में गतिशीलता का उपयोग करने के अलावा कोई विकल्प नहीं है जो डेटाबेस से मूल्य प्राप्त करता है। तो मुझे लगता है कि मुझे बस सूची के साथ जाना चाहिए। – IamIC

+1

@IanC मैं जो भी सरल कोड उत्पन्न करूंगा, उसके साथ जाऊंगा, और फिर बाद में गति के बारे में चिंता करें। – jbtule

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