2015-12-29 8 views
6

मुझे सी # में जेनेरिक पसंद है, लेकिन कभी-कभी उनके साथ काम करना थोड़ा जटिल हो सकता है। नीचे की समस्या मैं अब और फिर हर समय दौड़ता हूं। क्या इस परिदृश्य को सरल बनाने का कोई तरीका है? मैं कैसे नहीं देख सकते हैं, लेकिन मैं आशा करती हूं कि किसी कोक्या सी # में नेस्टेड जेनरिक को सरल बनाना संभव है?

कर सकते हैं :) तीन आधार वर्ग को देखते हुए:

public abstract class Inner 
{ 
} 

public abstract class Outer<T> 
    where T : Inner 
{ 
} 

public abstract class Handler<TOuter, TInner> 
    where TOuter : Outer<TInner> 
    where TInner : Inner 
{ 
    public abstract void SetValue(TInner value); 
} 

और कुछ सरल कार्यान्वयन:

public class In : Inner 
{ 
} 

public class Out : Outer<In> 
{ 
} 

public class HandleOut : Handler<Out, In> 
{ 
    public override void SetValue(In value) { } 
} 

अब मेरी सवाल यह है: के लिए HandleOut, TInner का प्रकार "आउट" प्रकार से दिया गया है, इसलिए HandleOut की परिभाषा को public class HandleOut : Handler<Out> जैसी परिभाषा को सरल बनाने का कोई तरीका है और अभी भीपर पैरामीटर के रूप में आंतरिक प्रकार का उपयोग करने में सक्षम होना है?

यह एक बहुत ही सरल उदाहरण है, लेकिन मुझे कभी-कभी परिभाषाओं में जेनेरिक प्रकारों की एक लंबी सूची मिलती है, जब आमतौर पर उन सभी को तर्कसंगत रूप से पहले प्रकार से घटाया जा सकता है। क्या कोई ऐसी चीज है जो मुझे याद आ रही है?

+2

मैंने आपके कोड को ठीक किया ताकि यह संकलित हो। क्या आप यह देखने के लिए जांच सकते हैं कि यह आपके प्रश्न के पीओवी से सही है या नहीं? – Enigmativity

+4

जबकि मुझे लगता है कि आप जो सोच रहे हैं उसके साथ 100% गठबंधन नहीं है, तो आप एरिक लिपर्ट द्वारा एक ब्लॉग पोस्ट पढ़ना चाहेंगे [जेनेरिक बाधाएं विरासत में क्यों नहीं हैं] (http://ericlippert.com/2013/07/15/ क्यों-जेनेरिक-बाधाएं-विरासत में नहीं मिलीं /) (और, वास्तव में, तथ्य यह है कि वे विरासत में नहीं हैं इसलिए क्यों * निष्क्रियता को आपके कोड को * अधिक * बाधाओं को जोड़ने के लिए ठीक करना पड़ा) –

+0

धन्यवाद, @Enigmativity। मैंने बस फ्लाई पर कोड लिखा - आपके परिवर्तन बिल्कुल मेरे विचारों के अनुसार हैं :) –

उत्तर

1

सं

जबकि इस तरह के निष्कर्ष शायद संभव हो जाना चाहिए, यह भाषाओं का का हिस्सा नहीं है। आप इसे Roslyn (एक नई समस्या खोलें) को सुझाव देने में रुचि रखते हैं। बेशक इस प्रकार की सामान्य बाधाओं की जटिलता जटिल मामलों में समस्या में पड़ सकती है, लेकिन कम से कम सरल लोगों के लिए यह करने योग्य है ... फिर भी, क्या सी # टीम को अपना समय और प्रयास करना चाहिए?

लिंक Why are generic constraints not inherited कि Damien_The_Unbelievershared on the comments स्थान पर है।


वैसे भी, कोड में अपने प्रस्तुत करते हुए यह जरूरी है कि पहले से ही आप Out प्रकार In, सामान्य पैरामीटर TOuter की जरूरत नहीं है देने के सच है।

निम्नलिखित कोड समान रूप से अच्छी तरह से काम करता है:

public abstract class Inner 
{ 
} 

public abstract class Outer<T> 
    where T : Inner 
{ 
} 

public abstract class Handler<TInner> // NOTE: TOuter removed 
    where TInner : Inner 
{ 
    public abstract void SetValue(TInner value); 
} 

public class In : Inner 
{ 
} 

public class Out : Outer<In> 
{ 
} 

public class HandleOut : Handler<In> // NOTE: Out removed 
{ 
    public override void SetValue(In value) { } 
} 

तो, TOuter के बजाय Outer<TInner> का उपयोग कर यदि आपको आवश्यकता पर विचार कर सकते। बेशक, यदि आप TOuter की सूची रखते हैं तो यह कम प्रतिबंधक होगा क्योंकि यह किसी भी व्युत्पन्न प्रकार Outer<TInner> किसी भी व्युत्पन्न प्रकार TOuter के बजाय अनुमति देगा।

चूंकि आपने सामान्य बाधा पर "नया" नहीं रखा है, इसलिए आप इस प्रकार की वस्तुएं नहीं बना रहे हैं, लेकिन यदि मामला आता है, तो आप कन्स्ट्रक्टर में Func<Outer<TInner>> स्वीकार कर सकते हैं।

+0

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

+0

@ChrisRidge कि वाक्यविन्यास काम कर सकता है, लेकिन शायद ही जिस तरह से सिस्टम सामान्य रूप से किया जाता है, उसके बाद से जेनेरिक पैरामीटर अंतर्निहित था या नहीं। यही कारण है कि मैं इसे व्युत्पन्न प्रकार पर अनुमान के रूप में देखता हूं। आपके पास कितने सामान्य पैरामीटर हैं? [मैं 4 से अधिक के लिए एक मामले के बारे में नहीं सोच सकता] शायद यह आपके द्वारा विकसित किए जा रहे कार्यों का एक हिस्सा है, या शायद आप कुछ अमूर्तता खो रहे हैं ... फिर भी अगर यह किसी विशेष मामले को आसान बनाता है तो शायद रोस्लिन टीम द्वारा रुचि हो सकती है। वैकल्पिक पर विचार करें - इसकी वास्तव में आवश्यकता नहीं है, लेकिन यह इंटरऑप और कोड रखरखाव को आसान बनाता है। – Theraot

+0

मेरी वर्तमान परियोजना में मुझे चार से अधिक नहीं मिला है, लेकिन ये इंटरफेस में हैं जो कई बार लागू किए जाते हैं। प्रत्येक कार्यान्वयन के लिए सभी चार प्रकार निर्दिष्ट करने के लिए कठिन है और कोड को समझने में कठोर बनाता है। यह बिल्कुल जरूरी नहीं है, लेकिन हमारे लिए यह एक शानदार सुविधा होगी :) –

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