2008-11-21 23 views
27

क्या डिज़ाइन-टाइम पर प्रकार जानने के बिना जेनेरिक का एक उदाहरण घोषित करना संभव है?गतिशील रूप से एक सामान्य प्रकार के उदाहरण घोषित करें

उदाहरण:

Int i = 1; 
List<typeof(i)> list = new List<typeof(i)>(); 

मैं कहाँ के प्रकार, कुछ भी हो सकता बजाय क्या करने वाले की:

List<int> list = new List<int(); 

उत्तर

43

आप में प्रकार पता नहीं है संकलन समय है, लेकिन आप वास्तविक प्रकार (यानी नहीं List<object>) और आप उचित प्रकार पैरामीटर के साथ एक सामान्य विधि/प्रकार में नहीं कर रहे हैं चाहते हैं, तो आप प्रतिबिंब का उपयोग करना होगा।

प्रतिबिंब आसान बनाने के लिए , मैंने कभी-कभी अपने स्वयं के कोड में एक नया जेनेरिक प्रकार या विधि पेश की है, इसलिए मैं इसे प्रतिबिंब द्वारा कॉल कर सकता हूं लेकिन n उसके बाद सामान्य जेनेरिक का उपयोग करें। उदाहरण के लिए:

object x = GetObjectFromSomewhere(); 
// I want to create a List<?> containing the existing 
// object, but strongly typed to the "right" type depending 
// on the type of the value of x 
MethodInfo method = GetType().GetMethod("BuildListHelper"); 
method = method.MakeGenericMethod(new Type[] { x.GetType() }); 
object list = method.Invoke(this, new object[] { x }); 

// Later 

public IList<T> BuildListHelper<T>(T item) 
{ 
    List<T> list = new List<T>(); 
    list.Add(item); 
    return list; 
} 

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

संपादित करें: ध्यान दें कि हालांकि मैं ऊपर दिए गए कोड में Type.GetMethod को कॉल कर रहा हूं, अगर आप इसे निष्पादित करने जा रहे थे तो शायद आप इसे केवल एक बार कॉल करना चाहते हैं - आखिरकार, विधि नहीं जा रही है बदलने के लिए। आप इसे स्थैतिक बना सकते हैं (आप उपरोक्त मामले में कर सकते हैं) और आप शायद इसे निजी बनाना चाहते हैं। मैंने इसे नमूना कोड में GetMethod कॉल की सादगी के लिए सार्वजनिक उदाहरण विधि के रूप में छोड़ा - आपको अन्यथा उचित बाध्यकारी झंडे निर्दिष्ट करने की आवश्यकता होगी।

+0

आप एक गैर-जेनेरिक IList (जो सूची <>) द्वारा समर्थित है, लौटा सकता है, तो लौटाई गई सूची का उपयोग किया जाएगा। – configurator

+0

किस मामले में शुरुआत करने के लिए एक ArrayList का उपयोग करना आसान होगा। –

+0

आह, लेकिन जब इसे आईएलिस्ट के रूप में डाला जाता है तो संग्रह में गलत प्रकार जोड़ना गलत प्रकार के बारे में अपवाद के माध्यम से होगा, है ना? – Sekhat

1

मुझे लगता है कि सबसे अच्छा आप ऐसा करने में सक्षम होने जा रहे हैं की तरह कुछ है यह:

static void Main(string[] args) 
{ 
    int i = 1; 
    var thelist = CreateList(i); 
} 

public static List<T> CreateList<T>(T t) 
{ 
    return new List<T>(); 
} 
+1

कि संकलक प्रकार अनुमान लगाने के लिए सक्षम किया जा रहा पर निर्भर करता है - यानी उसे संकलन समय पर प्रकार पता करने के लिए है। –

0

बहुत यकीन है कि आप ऐसा कर सकते हैं, उन्हें टेम्पलेट्स जैसे संकलित समय पर ठीक करने की आवश्यकता नहीं है C++।

एक उदाहरण यहां इसी तरह की है कि: http://geekswithblogs.net/marcel/archive/2007/03/24/109722.aspx

1

आप डिजाइन समय में प्रकार पता नहीं है, तो मैं कहेंगे आप एक (अन्य सभी प्रकार के लिए आधार वर्ग) वस्तुओं की सूची है।

List<object> list = new List<object>(); 
+1

नहीं, आप अभी भी उचित प्रकार की एक सूची बना सकते हैं और इसे किसी ऐसे व्यक्ति को पास कर सकते हैं जो सही प्रकार पर कलाकार डालने में सक्षम हो और इसके साथ एक स्थिर टाइप किए गए तरीके से इसके साथ काम कर सके। सिर्फ इसलिए कि कोड का एक टुकड़ा इस प्रकार का नहीं जानता है इसका मतलब यह नहीं है कि * कुछ नहीं * प्रकार जानता है। –

1

आप एक्टिवेटर.क्रेट इंस्टेंस का भी उपयोग कर सकते हैं। उदाहरण कोड का टुकड़ा:

public class BaseRepository<T> where T : DataContext 
{ 
    protected T _dc; 

    public BaseRepository(string connectionString) 
    { 
     _dc = (T) Activator.CreateInstance(typeof(T), connectionString); 
    } 

    public void SubmitChanges() 
    { 
     _dc.SubmitChanges(); 
    } 
} 
0

समान प्रश्न "Dynamically Create a Generic Type for Template" से उत्तर देखें। केवल अंतर यह है कि वे कमांड लाइन से प्रकार उत्पन्न कर रहे हैं, बाकी आप अपनी जरूरतों को अनुकूलित करने में सक्षम होना चाहिए।

एक के रूप में अलग रूप में, आप एक उदाहरण पर typeof फोन नहीं कर सकते हैं - (उदाहरण के लिए एक उदाहरण के प्रकार के प्राप्त करने के लिए "मैं" कहते हैं GetType():

Type intType = i.GetType(); 
0

आप अभी भी .Add(), .remove() टाइप करने के लिए चाहते हैं, करते हैं foreach आदि आप के रूप में एक नियमित रूप से "पुराने" System.Collections.IList, सूची इलाज कर सकते हैं के बाद से इस इंटरफेस सौभाग्य से सूची से कार्यान्वित किया जाता है < टी>।

और चूंकि अन्य सभी इस सवाल का उत्तर पोस्ट काफी एक सूची < का एक उदाहरण टी> गतिशील, मैं यह करने के लिए एक आखिरी रास्ता दिखाएगा बनाने के लिए हर दूसरे संभव तरीके से पता चलता है। सामान्य उदाहरण बनाते समय मैं व्यक्तिगत रूप से इस विधि का उपयोग करता हूं, जब मुझे संकलन समय, पर प्रकार के बारे में कुछ भी नहीं पता है और प्रकार को स्ट्रिंग के रूप में पारित किया जाना चाहिए, शायद एप्लिकेशन कॉन्फ़िगरेशन फ़ाइल से आ रहा है। इस उदाहरण में, टी सादगी के लिए System.String है, लेकिन यह कुछ भी हो सकता है:

Type T = typeof (string); // replace with actual T 
string typeName = string.Format (
    "System.Collections.Generic.List`1[[{0}]], mscorlib", T.AssemblyQualifiedName); 

IList list = Activator.CreateInstance (Type.GetType (typeName)) 
    as IList; 

System.Diagnostics.Debug.Assert (list != null); // 

list.Add ("string 1"); // new T 
list.Add ("string 2"); // new T 
foreach (object item in list) 
{ 
    Console.WriteLine ("item: {0}", item); 
} 
संबंधित मुद्दे