2010-08-31 5 views
6

मैं सफलता के बिना निम्नलिखित डिजाइन कोशिश कर रहा हूँ:क्या सी # में अनियमित जेनरिक की सूची का उपयोग करना संभव है?

abstract class Foo<T> 
{ 
    abstract T Output { get; } 
} 

class Bar 
{ 
    List<Foo> Foos; 
} 

मैं एक सरणी सूची का उपयोग कर नापसंद हैं, क्योंकि मैं प्रकार प्राप्त करने के लिए असुरक्षित डाले का उपयोग करना होगा। मैं फू को टाइप करना चाहता हूं ताकि "आउटपुट" केवल एक ऑब्जेक्ट न हो, इस मामले में मुझे असुरक्षित जानवरों का भी उपयोग करना होगा।

जैसा कि मेरा कोड फिलहाल है, मैं एक ऑब्जेक्ट के रूप में आउटपुट के साथ फू का उपयोग करता हूं।

+0

सटीक अनुलिपि: http://stackoverflow.com/questions/353126/c-multiple-generic-types-in-one-list – GameZelda

उत्तर

8

का उदाहरण अगर मैं तुम्हें सही ढंग से समझ, आप Foo वस्तुओं जो Output रों के विभिन्न प्रकार की एक सूची, है ना? चूंकि ये आउटपुट विभिन्न प्रकार के होते हैं, इसलिए आपको यहां वैसे भी कास्ट करना होगा।

हालांकि, निम्न विचार मदद कर सकता है। कैसे के बारे में आप IFoo नामक एक गैर सामान्य इंटरफ़ेस की घोषणा:

public interface IFoo 
{ 
    object Output { get; } 
} 

¹ और फिर अपने अमूर्त वर्ग में इसे लागू:

class Bar 
{ 
    List<IFoo> Foos; 
} 
:

abstract class Foo<T> : IFoo 
{ 
    abstract T Output { get; } 
    object IFoo.Output { get { return Output; } } 
} 

तो फिर तुम IFoo रों की एक सूची घोषित कर सकते हैं

उन फ़ूज़ तक पहुंचने पर, आप या तो आउटपुट को इंटरफ़ेस के माध्यम से ऑब्जेक्ट के रूप में पुनर्प्राप्त कर सकते हैं:

var myObject = Foos[0].Output;  // type ‘object’ 

या आप वास्तविक प्रकार की खोज के लिए यदि आप जानते हैं कि यह केवल कुछ विशिष्ट प्रकार के हो सकते हैं की कोशिश कर सकते हैं:

if (Foos[0] is Foo<string>) 
    var myString = ((Foo<string>) Foos[0]).Output; // type ‘string’ 

यहां तक ​​कि आप उदाहरण के लिए, प्रकार के आधार पर छानने कार्य करें:

// Type ‘IEnumerable<string>’ (rather than ‘IEnumerable<object>’)! 
var stringFoos = Foos.OfType<Foo<string>>().Select(f => f.Output); 

¹ आप भी इस एक सार आधार Foo बुलाया वर्ग बनाने के लिए और Foo<T> यह से निकाले जाते हैं हो सकता है। उस स्थिति में, आपको को new कीवर्ड के साथ चिह्नित करना होगा और सार आधार सदस्य तक पहुंचने के लिए base.Output का उपयोग करना होगा।

+0

धन्यवाद। :) ठीक वही जो मेरे द्वारा खोजा जा रहा था। – Lazlo

0

List<Foo>Foo के बाद से अमान्य है और एक क्लास निर्दिष्ट है, भले ही यह एक सामान्य है (List<Foo<U> >)।

+0

जेनरिक टेम्पलेट्स ... –

+0

यह यह होगा नहीं हैं। बार जेनेरिक बनाएं (टाइप पैरामीटर टी भी हो सकता है, या यू, या जो भी हो) और फू ओपन रखने के लिए टाइप पैरामीटर का उपयोग करें।जब आप नियंत्रण रखते हैं तो आप कंटेनर पदानुक्रम तक इसे कर सकते हैं; हालांकि, किसी बिंदु पर आपको कक्षा (ईएस) का उपभोग करने के लिए ठोस प्रकार के साथ सामान्य कार्यान्वयन को बंद करना होगा। यदि आप गतिशील रूप से ऐसा करना चाहते हैं, तो आप टाइप ऑब्जेक्ट या स्ट्रिंग द्वारा पहचाने गए किसी प्रकार के लिए बंद जेनेरिक ऑब्जेक्ट को तुरंत चालू करने के लिए प्रतिबिंब का उपयोग कर सकते हैं, लेकिन यह गन्दा वास्तविक हो सकता है। – KeithS

0

नहीं, आप इस तरह से जेनेरिक का उपयोग नहीं कर सकते हैं। आपको या तो Bar पर एक सामान्य प्रकार पैरामीटर जोड़ने की आवश्यकता है और इसे Foo<T> पर अग्रेषित करें या Bar प्रकार में Foo<T> का बंद उदाहरण प्रदान करें।

पहले

class Bar<T> { 
    public List<Foo<T>> Foos; 
} 
+1

मुझे लगता है कि वह जानता है कि। यह वह नहीं था जिसका मतलब था। – Timwi

+1

@ तिमवी, तो ओपी को प्रश्न में और स्पष्ट होना चाहिए। जब एक अस्पष्ट सवाल का सामना करना पड़ता है तो गलत जवाब देना बहुत आसान होता है। मेरे और दूसरों के लिए downvote अनचाहे है। आपके तर्क से मुझे आपको मुझसे अलग व्याख्या करने के लिए डाउनवोट करना चाहिए। – JaredPar

+0

मैं मानता हूं, मुझे ऐसे संदिग्ध प्रश्न भी परेशान करते हैं। यह मानना ​​बहुत आसान है कि किसी की अपनी व्याख्या सही है - इसके बारे में खेद है! (बेशक यह मदद करेगा अगर @ लाज़लो ने इस पर कुछ प्रकाश डाला ...) (गेमजेल्डा मेरे साथ सहमत है, हालांकि :)) – Timwi

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