2009-04-14 18 views
8

संभव डुप्लिकेट:
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?सी # में सामान्य विरासत?

मैं

public class MyGenericClass : DL 
//but i cannot do 
public class MyGenericClass <T> : T 

कर सकते हैं मैं कैसे दूसरे करना होगा? अगर मैं ऐसा नहीं कर सकते, मैं कैसे की तरह

public class MyGenericClass <T> 
{ 
    T obj; 
    //have all MyGenericClass.XYZ call obj.XYZ 
} 
+0

ऐसा करने की कोशिश करने के लिए आपकी प्रेरणा क्या है? –

+0

सी # 4.0 में गतिशील प्रकार की प्रतीक्षा करें। –

उत्तर

9

कुछ इस संभव नहीं है क्या कर सकते हैं, क्योंकि है कि किस प्रकार टी के आधार पर, MyGenericClass की सार्वजनिक इंटरफ़ेस बदल जाएगा।

आपको लगता है कि सभी एक ही इंटरफ़ेस का पर्दाफाश विभिन्न वर्गों के बहुत सारे है, तो आप कि इंटरफ़ेस का पर्दाफाश करने के MyGenericClass घोषित कर सकता है, और कार्यों के सभी के कार्यान्वयन में obj को

+0

लेकिन दूसरे मामले में, जहां टी को सदस्य घोषित करने के लिए उपयोग किया जाता है, वह सदस्य सार्वजनिक हो सकता है, और फिर MyGenericClass का सार्वजनिक इंटरफ़ेस T. –

+0

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

+0

यह परिपत्र है: "मूल रूप से जेनेरिक द्वारा संभाला जाता है" - यह उस मामले को निहित रूप से क्यों संभालता है जो ' टी काम नहीं करते? :) –

4

आप की तरह कुछ कर सकता है कॉल प्रतिनिधि

public interface IXyzable { void xyz(); } 

public class MyGenericClass<T> : IXyzable where T : IXyzable { 
    T obj; 
    public void xyz() { 
     obj.xyz(); 
    } 
} 

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

+0

क्या आप कृपया मुझे इस क्लास फ़ंक्शन को कॉल करने के लिए एक वर्किंग कोड प्रदान कर सकते हैं? – Elangesh

+0

मैंने निम्नलिखित कोड MyGenericClass myGenericClass = new MyGenericClass (); कंसोल। राइटलाइन (myGenericClass.xyz()); कंसोल। रीडलाइन(); – Elangesh

+0

चेकआउट http://stackoverflow.com/questions/3419176/how-to-use-the-where-keyword-in-c-sharp-with-a-generic-interface-and-inherita –

0

लीजिए, आपके संभव टी कुछ इंटरफ़ेस को लागू करने, ताकि आप जानते हैं कि obj.XYZ() समझ में आता है की, तो आप

0 क्या कर सकते हैं की आवश्यकता होगी समझते हैं
public interface Ixyz 
{ 
    void XYZ(); 
} 

public class MyGenericClass<T> : Ixyz where T:Ixyz, new() 
{ 
    T obj; 

    public MyGenericClass() 
    { 
     obj = new T(); 
    } 

    public void XYZ() 
    { 
     obj.XYZ(); 
    } 
} 

मैं MyGenericClass लागू Ixyz भी के बाद से यह स्पष्ट रूप से सही विधि का पर्दाफाश करता है बनाया है, लेकिन शायद यह है कि सबसे अच्छा बाहर छोड़ दिया है के बाद से यह

var x = new MyGenericClass<MyGenericClass<SomeClass>>(); 

जो कभी एक अच्छा विचार होने की संभावना नहीं है की अनुमति देता है।

0

यह बहुत अधिक बतख-टाइपिंग है, लेकिन आप प्रतिबिंब का उपयोग कर सकते हैं। जब आप ओब्जे के संदर्भ के साथ जेनेरिक क्लास बनाते हैं, तो सही हस्ताक्षर के साथ विधि को खोजने और खोजने के लिए प्रतिबिंब का उपयोग करें। जब तक आप विधि के संदर्भ को संग्रहीत करते हैं, तब तक प्रदर्शन बहुत खराब नहीं होगा।

class BaseGeneric<T> 
{ 
    private T obj; 
    private MethodInfo mi; 
    private const string MethodNameOfInterest = "Xyz"; 

    public BaseGeneric(T theObject) 
    { 
     this.obj = theObject; 
     Type t = obj.GetType(); 
     mi = t.GetMethod(MethodNameOfInterest); 
    } 

    public void Xyz() 
    { 
     mi.Invoke(obj, null); 
    } 
} 

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

+0

नीचे वोट क्यों? मैंने सवाल का जवाब दिया, है ना? मैं इसे करने की अनुशंसा नहीं करता, लेकिन यह उसकी समस्या का समाधान करता है: बेसजेनेरिक .Xyz() अंतर्निहित ऑब्जेक्ट की Xyz() विधि को कॉल करता है इससे कोई फर्क नहीं पड़ता कि वह किस प्रकार का है। –

+0

आपके समाधान में प्रतिबिंब के सभी डाउनसाइड्स हैं, और बतख टाइपिंग का कोई लाभ नहीं है। बाहरी ऑब्जेक्ट (बेसजेनेरिक) में इसके सभी घोषित घोषित होना चाहिए। यदि आप उन कार्यों को जानते हैं, तो बस एक ही फ़ंक्शन को कॉल करें? –

+0

यह MethodInfo को कैश करता है, इसलिए प्रदर्शन जुर्माना कम हो जाता है। यह अंतर्निहित वस्तु की तरह दिखता है - इसलिए यह quacks। यह उसे फिर से हर विधि को लागू करता है, इसलिए यह सबसे बड़ा नकारात्मक पक्ष है। हालांकि, टी कुछ भी हो सकता है जो Xyz लागू करता है, जो कुछ परिदृश्यों में आसान होता है। –

1

.NET प्रकार प्रणाली आपके द्वारा किए जा रहे फ़ॉर्म की प्रकार की घोषणाओं की अनुमति नहीं देगी। इसे अस्वीकार करने का एक कारण सहज होना चाहिए: MyGenericClass<T> कार्य कब T एक सीलबंद वर्ग (उदा। System.String) है?

आप पूरी तरह इस कार्यक्षमता की जरूरत है (और आप जानते हैं कि प्रकार T आप का उपयोग किया जाएगा सील नहीं है), तो आप Reflection.Emit नाम स्थान में वर्गों का उपयोग क्रम में प्रॉक्सी उत्पन्न कर सकते हैं। PostSharp जैसे AOP टूल का उपयोग करके इस प्रभाव को प्राप्त करना भी संभव हो सकता है।आप ऐसा कर सकते

public class MyGenericClass<T> : T 

और::

+0

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

4

विशिष्ट प्रश्न, तुमने ऐसा क्यों नहीं कर सकते

public class MyGenericClass<T> 
{ 
    T obj; 
} 

कारण यह है कि CLR एक भी संकलित करने के लिए सक्षम होने के लिए पसंद करती है है MyGenericClass के लिए कोड का संस्करण जो टी

के लिए निर्दिष्ट किसी संदर्भ प्रकार के लिए काम करेगा, यह दूसरे मामले के लिए ऐसा कर सकता है, क्योंकि यह T कोके साथ चुपचाप बदल सकता हैऔर सम्मिलित उचित डाले, मोटे तौर पर के बराबर:

public class MyGenericClass 
{ 
    object obj; 
} 

लेकिन विरासत संस्करण के लिए, कि चाल काम नहीं करता।

इसके अलावा, कई उपयोगी सुविधाएं इंटरफ़ेस बाधाओं के माध्यम से वर्णन करना असंभव होगा। जब आप किसी प्रकार से उत्तराधिकारी होते हैं, तो आप केवल कॉल विधियों की तुलना में बहुत कुछ कर सकते हैं - आप उन्हें ओवरराइड भी कर सकते हैं। इस काल्पनिक उदाहरण पर विचार करें:

class MyBase 
{ 
    public virtual void MyVirtual() { } 
} 

class MyGenericDerived<T> : T 
{ 
    public override void MyVirtual() 
    { 
     Console.WriteLine("Overridden!"); 
    } 
} 

MyBase obj = new MyGenericDerived<MyBase>(); 
obj.MyVirtual(); 

क्या मैं वहाँ एक "मिश्रण-इन", जहां MyGenericDerived आभासी कार्यों जो आधार में इसे करने के लिए लागू किया जाता है के लिए परिभाषाओं की आपूर्ति की तरह कुछ है करना चाहते हैं। लेकिन संकलक कैसे जानता है कि टी में MyVirtual नामक एक विधि होगी जिसे ओवरराइड किया जा सकता है? मुझे टी पर बाधा डालना होगा। मैं इसे इंटरफेस के माध्यम से कैसे व्यक्त करूं? यह नामुमकिन है। एक बार जब आप विरासत को टाइप पैरामीटर से अनुमति देते हैं तो बाधाओं का वर्णन करने के लिए इंटरफेस का उपयोग करना पर्याप्त समाधान नहीं है। तो यह एक और कारण है कि आज यह भाषा में क्यों मौजूद नहीं है।

0
इस बारे में

क्या:

class BaseClass<T> 
{ 
    public T property { get; set; } 
} 

class GenericClass<T> : BaseClass<T> 
{ 

} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     GenericClass<int> l = new GenericClass<int>(); 
     l.property = 10; 
    } 
} 

इस को प्राप्त होता है कि आप क्या करना चाहते हैं?

+0

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

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