2009-11-29 15 views
16

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

public class SomeClass<T> 
{ 
    public virtual void SomeMethod(){ } 
} 

public class DeriveFrom :SomeClass<string> 
{ 
    public override void SomeMethod() 
    { 
     base.SomeMethod(); 
    } 
} 

बात कर रहा हूँ का एक बहुत ही सरल उदाहरण समस्या आ जाती है जब मैं तो एक बहुरूपी तरह से व्युत्पन्न उदाहरणों का उपयोग करना चाहते।

public class ClientCode 
{ 
    public void DoSomethingClienty() 
    { 
     Factory factory = new Factory(); 
     //Doesn't compile because SomeClass needs a type parameter! 
     SomeClass someInstance = factory.Create(); 

     someInstance.SomeMethod(); 
    } 
} 

ऐसा लगता है कि एक बार आप एक वंशानुगत पदानुक्रम या इंटरफ़ेस में एक सामान्य परिचय, आप अब कक्षाओं की है कि परिवार एक बहुरूपी तरह से शायद ही आंतरिक छोड़कर उपयोग कर सकते हैं। क्या यह सच है?

+3

मुझे लगता है कि SomeClass DeriveFrom का बेस क्लास है, न कि कुछ क्लास, जो आपको लगता है कि यह होना चाहिए। – Thanatos

उत्तर

11

जहाँ तक मैं देख सकता हूं, उपभोग करने वाले कोड को सामान्य वर्ग के विशिष्टताओं की आवश्यकता नहीं होती है (यानी, यह T पर निर्भर नहीं है)। तो, आप इंटरफ़ेस क्यों नहीं पेश करते हैं कि SomeClass<T> लागू होगा, और इस इंटरफ़ेस का उदाहरण उपयोग करें।

उदा .:

public interface ISome 
{ 
    void SomeMethod(); 
} 

public class SomeClass<T>: ISome 
{ 
    public virtual void SomeMethod(){ } 
} 

public void DoSomethingClienty() 
{ 
    Factory factory = new Factory(); 
    ISome someInstance = factory.Create(); 

    someInstance.SomeMethod(); 
} 

अब, SomeClass<T> की उपवर्गों अलग T रों पर अलग ढंग से काम कर सकते हैं, लेकिन उपभोक्ता कोड परिवर्तन नहीं होगा।

+0

मुझे लगता है कि यह सबसे अच्छा समाधान है। हम केवल उस इंटरफ़ेस का विस्तार करते हैं जिस पर ग्राहक परवाह है और हम हुड के तहत जेनेरिक को छुपाते हैं। –

9

मुझे लगता है कि आप जेनेरिक के बिंदु को गलत समझ रहे हैं। जेनेरिक आपको एक ऐसे वर्ग को सामान्यीकृत करने की अनुमति देता है जिसके लिए एक प्रकार की आवश्यकता होती है, लेकिन विशेष रूप से स्वयं की देखभाल नहीं करता है कि यह किस प्रकार है। उदाहरण के लिए, List<string> तारों की एक सूची है, लेकिन List क्या होगा? यह कुछ भी नहीं की सूची रखने के लिए एक बेकार अवधारणा है।

प्रत्येक विशेष श्रेणी (यानी, List<string>) यह स्वयं का विशिष्ट प्रकार है, और संकलक इसे इस तरह से मानता है। यह संभव सामान्य प्रकार पर प्राप्त करने के लिए (typeof(List<>) उदाहरण के लिए) है, लेकिन ज्यादातर मामलों में यह बेकार है, और आप निश्चित रूप से इसका उदाहरण नहीं बना सकते हैं।

2

मैं सभी सामान्य प्रकारों के आधार के रूप में कार्य करने के लिए अमूर्त वर्ग का उपयोग करना पसंद करूंगा।

public abstract class SomeClass 
{ 
    public abstract void SomeMethod(); 
} 

public class SomeClass<T> : SomeClass 
{ 
    public override void SomeMethod() { }    
} 

public class DeriveFrom<String> : SomeClass<String> 
{ 
    public override void SomeMethod() { base.SomeMethod(); }    
} 
+0

वास्तव में, लेकिन 'फैक्टरी' यहां कैसे काम करेगा? –

+0

निक द्वारा वर्णित "फैक्टरी" के कार्यान्वयन के बारे में कोई जानकारी नहीं है। लेकिन मुझे पूरा यकीन है, यह अमूर्त गैर-जेनेरिक 'SomeClass' में बहुत अच्छी तरह से कार्यान्वित किया जा सकता है। –

+0

@ एम्बी लेकिन अगर आप अमूर्त शून्य कुछ विधि() में वापसी प्रकार टी और प्रकार टी के पैरामीटर है तो आप क्या करेंगे? फिर आप जेनेरिक को अपने गैर-जेनेरिक अमूर्त वर्ग के नीचे छुपा नहीं सकते हैं। मैं आपसे एक उत्तर या टिप की सराहना करता हूं :) – Elisabeth

0

मुझे लगता है कि आप के लिए देख रहे हैं:

 SomeClass(of someType) someInstance = factory(of someType).Create(); 
or maybe 
    SomeClass(of someType) someInstance = factory.Create(of someType)(); 
or 
    SomeClass(of someType) someInstance = factory.Create(); 

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

0

ऐसा लगता है कि एक बार आप एक वंशानुगत पदानुक्रम या इंटरफ़ेस में एक सामान्य परिचय, आप अब कक्षाओं की है कि परिवार एक बहुरूपी रास्ता

सही में उपयोग कर सकते हैं, यह काफी इस स्थिति के समान है:

class StringContainer 
{ 
} 

class IntContainer 
{ 
} 

StringContainer container = new IntContainer(); // fails to compile 

लेकिन आप ऐसा कर सकता है:

class Container 
{ 
} 

class Container<T> : Container 
{ 
} 

Container container = new Container<String>(); // OK 
0
public Class ReflectionReport<T> 
{ 
    // This class uses Reflection to produce column-based grids for reporting. 
    // However, you need a type in order to know what the columns are. 
} 

... so, in another class you have... 

public Class ReflectionReportProject { 
    ReflectionReport<Thang> thangReport = new ReflectionReport<Thang>(); 
    ReflectionReport<Thong> thongReport = new ReflectionReport<Thong>(); 



    ... some more stuff ... 

    // Now, you want to pass off all of the reports to be processed at one time.... 
    public ReflectionReport<????>[] ProvideReports() 
    { 
     return new ReflectionReport<????>[] { thangReport, thongReport } ; 
    } 
} 
+2

उपर्युक्त उदाहरण है कि जेनेरिक के साथ बहुरूपता वास्तव में उपयोगी कैसे होगी। – user1126454

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