2009-03-17 21 views
35

मैं स्ट्रिंग कुंजी के साथ एक शब्दकोश ऑब्जेक्ट बनाना चाहता हूं, जो सामान्य प्रकार के मान रखता है। मुझे लगता है कि यह कुछ इस तरह दिखेगा:क्या मैं सामान्य प्रकार का शब्दकोश बना सकता हूं?

Dictionary<string, List<T>> d = new Dictionary<string, List<T>>(); 

और मेरा पीछा जोड़ने के लिए सक्षम:

d.Add("Numbers", new List<int>()); 
d.Add("Letters", new List<string>()); 

मुझे पता है कि मैं स्ट्रिंग की एक सूची के लिए यह कर सकते हैं, उदाहरण के लिए, इस का उपयोग करते हुए वाक्य रचना:

Dictionary<string, List<string>> d = new Dictionary<string, List<string>>(); 
d.Add("Key", new List<string>()); 

लेकिन मैं यदि संभव हो तो एक सामान्य सूची के लिए यह करने के लिए करना चाहते हैं ...

2 प्रश्न तब:

  1. क्या यह संभव है?
  2. वाक्यविन्यास क्या है?

बहुत धन्यवाद,
जॉन

उत्तर

24

संपादित करें: अब मैं सवाल ...

आप ऐसा नहीं कर सकते पुन: पढ़ने की है, लेकिन एक कस्टम संकलन कुछ हद तक इसे संभाल होगा।

आप निकालने नहीं कर सका -

public void Add<T>(string key, List<T> list) 

(। जब तक आप कुंजी प्रकार सामान्य बनाना चाहते थे संग्रह ही सामान्य नहीं होगा): आप मूल रूप से एक सामान्य Add विधि होगा इससे दृढ़ता से टाइप किए गए तरीके से मूल्य, हालांकि संकलक को यह नहीं पता होगा कि आपने किस विशेष प्रकार के लिए किसी विशेष कुंजी के लिए उपयोग किया है। यदि आप कुंजी को स्वयं ही बनाते हैं, तो आप थोड़ा बेहतर स्थिति के साथ समाप्त होते हैं, लेकिन एक जो अभी भी मौजूदा संग्रह द्वारा समर्थित नहीं है। यही वह स्थिति है जहां मेरा मूल जवाब जवाब दे रहा था।

संपादित करें: मूल जवाब है, जब मैं काफी सही ढंग से सवाल नहीं पढ़ी थी, लेकिन जो वैसे भी जानकारीपूर्ण हो सकता है ...

नहीं, आप एक प्रकार तर्क नहीं कर सकते हैं एक और पर निर्भर करते हैं, मैं कर रहा हूँ डरा हुआ। यह उन चीजों में से एक है जो एक सामान्य प्रकार की प्रणाली में व्यक्त करना चाहते हैं, लेकिन .NET की बाधाओं की अनुमति नहीं है। हमेशा ऐसी समस्याएं होती जा रही हैं, और .NET डिजाइनरों ने जेनेरिक अपेक्षाकृत सरल रखना चुना है।

हालांकि, आप इसे आसानी से लागू करने के लिए एक संग्रह लिख सकते हैं। मेरे पास an example in a blog post है जो केवल एक मान रखता है, लेकिन सूची का उपयोग करने के लिए इसे विस्तारित करना आसान होगा।

+0

आह, मैं इस समस्या अब देखते हैं - क्या आप संग्रह से निकालने पर प्रकार निष्कर्ष करने के लिए कोई रास्ता नहीं है। मुझे लगता है कि यही कारण है कि इसे एक फीचर के रूप में शामिल नहीं किया गया है। धन्यवाद! –

+0

संग्रह स्वयं भी सामान्य हो सकता है: 'सी जहां टी: सी' का उपयोग उपयोगी होगा। – reinierpost

17

क्या इस काम को कुछ पसंद आएगा?

public class GenericDictionary 
{ 
    private Dictionary<string, object> _dict = new Dictionary<string, object>(); 

    public void Add<T>(string key, T value) where T : class 
    { 
     _dict.Add(key, value); 
    } 

    public T GetValue<T>(string key) where T : class 
    { 
     return _dict[key] as T; 
    } 
} 

असल में यह आपके लिए दृश्यों के पीछे सभी कास्टिंग लपेटता है।

3

मैं एक संग्रह में सामान्य प्रकार डालने की इस तरह से पसंद करते हैं:

interface IList 
{ 
    void Add (object item); 
} 

class MyList<T> : List<T>, IList 
{ 
    public void Add (object item) 
    { 
    base.Add ((T) item); // could put a type check here 
    } 
} 

class Program 
{ 
    static void Main (string [] args) 
    { 
    SortedDictionary<int, IList> 
     dict = new SortedDictionary<int, IList>(); 

    dict [0] = new MyList<int>(); 
    dict [1] = new MyList<float>(); 

    dict [0].Add (42); 
    dict [1].Add ("Hello"); // Fails! Type cast exception. 
    } 
} 

लेकिन तुम संकलन समय पर प्रकार के चेक खो देते हैं।

+0

बिल्कुल मैं क्या सोच रहा था: एक शब्दकोश <स्ट्रिंग, IList> का उपयोग करें। –

2

हम एक विस्तारणीय प्रशासन उपकरण बनाने के लिए बहुत सारे प्रतिबिंब का उपयोग कर रहे हैं। मॉड्यूल परिभाषा में वैश्विक खोज में वस्तुओं को पंजीकृत करने के लिए हमें एक तरीका चाहिए। प्रत्येक खोज परिणाम को लगातार तरीके से वापस कर देगी, लेकिन प्रत्येक के पास अलग-अलग निर्भरताएं थीं। यहाँ हमें एक भी मॉड्यूल के लिए खोज के पंजीकरण की एक उदाहरण है: मॉड्यूल पंजीकरण के दौरान

public void ConfigureSearch(ISearchConfiguration config) 
    { 
     config.AddGlobalSearchCallback<IEmploymentDataContext>((query, ctx) => 
     { 
      return ctx.Positions.Where(p => p.Name.Contains(query)).ToList().Select(p => 
       new SearchResult("Positions", p.Name, p.ThumbnailUrl, 
        new UrlContext("edit", "position", new RouteValueDictionary(new { Id = p.Id })) 
        )); 
     }); 
    } 

पृष्ठभूमि में, हम हर मॉड्यूल पर पुनरावृति और का एक उदाहरण के साथ एक SearchTable को समारोह जोड़ें:

public class GenericFuncCollection : IEnumerable<Tuple<Type, Type, Object>> 
{ 
    private List<Tuple<Type, Type, Object>> objects = new List<Tuple<Type, Type, Object>>(); 

    /// <summary> 
    /// Stores a list of Func of T where T is unknown at compile time. 
    /// </summary> 
    /// <typeparam name="T1">Type of T</typeparam> 
    /// <typeparam name="T2">Type of the Func</typeparam> 
    /// <param name="func">Instance of the Func</param> 
    public void Add<T1, T2>(Object func) 
    { 
     objects.Add(new Tuple<Type, Type, Object>(typeof(T1), typeof(T2), func)); 
    } 

    public IEnumerator<Tuple<Type, Type, object>> GetEnumerator() 
    { 
     return objects.GetEnumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return objects.GetEnumerator(); 
    } 
} 

फिर जब हम अंत में इसे कहते हैं, हम इसे प्रतिबिंब के साथ कार्य करें:

var dependency = DependencyResolver.Current.GetService(search.Item1); 
var methodInfo = search.Item2.GetMethod("Invoke"); 
return (IEnumerable<SearchResult>)methodInfo.Invoke(search.Item3, new Object[] { query, dependency }); 
1

अन्य posibility यह चर गतिशील उपयोग करने के लिए है।

उदाहरण के लिए:

Dictionary<string, List<dynamic>> d = new Dictionary<string, List<dynamic>>(); d.Add("Key", new List<dynamic>());

चर गतिशील क्रम पर प्रकार हल।

1

मुझे वह नहीं मिला जो मैं यहां देख रहा था लेकिन पढ़ने के बाद मुझे लगता है कि ऐसा उत्तर देने का प्रयास किया जा सकता है।

समस्या यह है कि जब आप शब्दकोश का उपयोग करते हैं तो यह एक बंद निर्मित प्रकार है और सभी तत्व टीवीएयू प्रकार का होना चाहिए। मैं इस सवाल को बिना किसी अच्छे उत्तर के कई स्थानों पर देखता हूं।

तथ्य यह है कि मैं अनुक्रमण करना चाहता हूं लेकिन प्रत्येक तत्व के पास एक अलग प्रकार है और टीके के मूल्य पर आधारित हम पहले से ही इस प्रकार को जानते हैं। मुक्केबाजी के चारों ओर जाने की कोशिश नहीं कर रहा है, लेकिन डेटासेट एक्सेन्शन फ़ील्ड जैसे कुछ और अधिक सुरुचिपूर्ण पहुंच प्राप्त करने का प्रयास कर रहा है। और गतिशीलता का उपयोग नहीं करना चाहते हैं क्योंकि प्रकार ज्ञात हैं और यह सिर्फ वांछित नहीं है।

एक समाधान एक सामान्य जेनेरिक प्रकार बनाने के लिए हो सकता है जो वर्ग स्तर पर टी का पर्दाफाश नहीं करता है और इसलिए शब्दकोश के टीवीएयू भाग को बंद करने का कारण बनता है। फिर प्रारंभ करने में मदद के लिए एक धाराप्रवाह विधि में छिड़कें।

Dictionary<string, object> d = new Dictionary<string, object>();

तो, यहाँ वस्तु डेटाप्रकार एक सामान्य डेटाप्रकार के रूप में प्रयोग किया जाता है, तो आप में कुछ भी रख सकते हैं:

public class GenericObject 
{ 
    private object value; 

    public T GetValue<T>() 
    { 
     return (T)value; 
    } 

    public void SetValue<T>(T value) 
    { 
     this.value = value; 
    } 

    public GenericObject WithValue<T>(T value) 
    { 
     this.value = value; 
     return this; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Dictionary<string, GenericObject> dict = new Dictionary<string, GenericObject>(); 

     dict["mystring"] = new GenericObject().WithValue<string>("Hello World"); 
     dict["myint"] = new GenericObject().WithValue<int>(1); 

     int i = dict["myint"].GetValue<int>(); 
     string s = dict["mystring"].GetValue<string>(); 
    } 
} 
0

तरीका में से एक के साथ प्रकार की तरह "वस्तु" एक शब्दकोश मान बनाने के लिए है यह एक मूल्य के रूप में।

0

कैसे के बारे में शब्दकोश मानते हुए कि आपके सी # पर हैं 4

Dictionary<string, dynamic> Dict = new Dictionary<string, dynamic>(); 

स्रोत: https://stackoverflow.com/a/5038029/3270733

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