क्या सी # जेनरिक में "डिफ़ॉल्ट" प्रकार के मापदंडों के लिए एक उचित दृष्टिकोण है?


91

C ++ टेम्प्लेट में, कोई निर्दिष्ट कर सकता है कि एक निश्चित प्रकार का पैरामीटर डिफ़ॉल्ट है। Ie जब तक स्पष्ट रूप से निर्दिष्ट नहीं किया जाता है, यह टाइप T का उपयोग करेगा।

क्या यह C # में किया या अंजाम दिया जा सकता है?

मैं कुछ इस तरह की तलाश में हूँ:

public class MyTemplate<T1, T2=string> {}

इस प्रकार का एक उदाहरण जो स्पष्ट रूप से निर्दिष्ट नहीं करता है T2:

MyTemplate<int> t = new MyTemplate<int>();

अनिवार्य रूप से होगा:

MyTemplate<int, string> t = new MyTemplate<int, string>();

अंतत: मैं एक ऐसे मामले को देख रहा हूं जिसमें एक खाका है जो काफी व्यापक रूप से उपयोग किया जाता है, लेकिन मैं एक अतिरिक्त प्रकार के पैरामीटर के साथ विस्तार करने पर विचार कर रहा हूं। मैं उपवर्ग कर सकता हूं, मुझे लगता है, लेकिन मैं उत्सुक था अगर इस नस में अन्य विकल्प थे।

जवाबों:


76

सबक्लासिंग सबसे अच्छा विकल्प है।

मैं आपके मुख्य सामान्य वर्ग को उपवर्गित करूंगा:

class BaseGeneric<T,U>

एक विशिष्ट वर्ग के साथ

class MyGeneric<T> : BaseGeneric<T, string>

यह आपके तर्क को एक स्थान (आधार वर्ग) में रखना आसान बनाता है, लेकिन उपयोग के दोनों विकल्प प्रदान करना भी आसान है। वर्ग के आधार पर, ऐसा करने के लिए संभवतः बहुत कम अतिरिक्त काम की आवश्यकता होती है।


1
आह ... जो समझ में आता है। यदि प्रकार पैरामीटर एक अद्वितीय हस्ताक्षर प्रदान करते हैं तो क्या प्रकार का नाम समान होने की अनुमति है?
el2iot2

2
@ee: हाँ, जेनेरिक overloadableपैरामीटर गणना द्वारा हैं ।
मेहरदाद अफश्री

@ee: हाँ, लेकिन मैं ऐसा करने से सावधान रहना होगा। ऐसा करने के लिए .NET में "कानूनी" है, लेकिन इससे भ्रम हो सकता है। मैं इसके बजाय स्ट्रिंग व्युत्पन्न प्रकार का नाम मुख्य सामान्य वर्ग के समान होगा (इसलिए यह स्पष्ट है कि यह क्या है / इसे खोजना आसान है), लेकिन एक नाम जो यह स्पष्ट करता है कि यह एक स्ट्रिंग है।
रीड कोपसी

@ लीड: क्या यह वास्तव में भ्रम पैदा करता है? इस विशिष्ट मामले के लिए, मुझे लगता है कि एक ही नाम होने से भी मदद मिलती है। .NET में ऐसे उदाहरण हैं जो समान काम करते हैं: उदाहरण के लिए Func <> प्रतिनिधि।
मेहरदाद अफश्री

4
उदाहरण के लिए, Predicate <T> सिर्फ Func <T, bool> है, लेकिन इसका नाम बदलकर एक अलग उद्देश्य के लिए रखा गया है।
रीड कोपसे

19

एक समाधान उपवर्ग है। एक और मैं इसके बजाय उपयोग करेगा, कारखाने के तरीके (संयुक्त कीवर्ड के साथ) है।

public class MyTemplate<T1,T2>
{
     public MyTemplate(..args..) { ... } // constructor
}

public static class MyTemplate{

     public static MyTemplate<T1,T2> Create<T1,T2>(..args..)
     {
         return new MyTemplate<T1, T2>(... params ...);
     }

     public static MyTemplate<T1, string> Create<T1>(...args...)
     {
         return new MyTemplate<T1, string>(... params ...);
     }
}

var val1 = MyTemplate.Create<int,decimal>();
var val2 = MyTemplate.Create<int>();

उपर्युक्त उदाहरण val2में प्रकार है MyTemplate<int,string> और इससे प्राप्त एक प्रकार नहीं है।

एक प्रकार एक class MyStringTemplate<T>:MyTemplate<T,string>ही प्रकार नहीं है MyTemplate<T,string>। यह कुछ परिदृश्यों में कुछ समस्याएँ पैदा कर सकता है। उदाहरण के लिए आप का एक उदाहरण डाली नहीं कर सकते MyTemplate<T,string>करने के लिए MyStringTemplate<T>


3
यह सबसे उपयोगी दृष्टिकोण है। बहुत अच्छा समाधान
T-moty

12

आप भी इस तरह एक वर्ग अधिभार बना सकते हैं

public class MyTemplate<T1, T2> {
    public T1 Prop1 { get; set; }
    public T2 Prop2 { get; set; }
}

public class MyTemplate<T1> : MyTemplate<T1, string>{}

कृपया उत्तर देने से पहले अन्य उत्तर पढ़ें, क्योंकि संभवत: आपका समाधान दूसरों की तरह ही है।
चेंग चेन

7
स्वीकृत उत्तर को अलग नाम से एक वर्ग बना रहा था, मेरा समाधान एक ही कक्षा को ओवरलोड कर रहा है
Nerdroid

2
नहीं, दोनों एक नया वर्ग बना रहे हैं। नाम यहाँ मायने नहीं रखता। MyTemplate<T1>से अलग वर्ग है MyTemplate<T1, T2>, न ही AnotherTemplate<T1>
चेंग चेन

7
यहां तक ​​कि अगर वास्तविक प्रकार अलग हैं, जो स्पष्ट और सही है, तो कोडिंग आसान है यदि आप एक ही नाम रखते हैं। यह सभी के लिए स्पष्ट नहीं है कि वर्ग "अधिभार" का उपयोग उस तरह से किया जा सकता है। @DannyChen सही है - तकनीकी दृष्टिकोण से परिणाम समान हैं, लेकिन ओपी ने जो मांगा वह हासिल करने के लिए यह उत्तर करीब है।
कुबा

1
दुर्भाग्य से यह समाधान अभी भी "डिफ़ॉल्ट" सामान्य तर्कों के लिए नीचा है, क्योंकि MyTemplate<T1, string>इसे असाइन नहीं किया जा सकता है MyTemplate<T1>, जो वांछनीय हो सकता है
फेल्क

9

C # ऐसी सुविधा का समर्थन नहीं करता है।

जैसा कि आपने कहा था, आप इसे उप-वर्ग कर सकते हैं (यदि यह सील नहीं किया गया है, और सभी निर्माणकर्ता घोषणाओं की नकल करते हैं) लेकिन यह पूरी तरह से अलग बात है।


2

दुर्भाग्य से सी # आप जो करने की कोशिश कर रहे हैं उसका समर्थन नहीं करता है। यह लागू करने के लिए एक कठिन विशेषता होगी कि किसी पैरामीटर के लिए डिफ़ॉल्ट प्रकार को सामान्य बाधाओं का पालन करना होगा और जब सीएलआर टाइप-सुरक्षा सुनिश्चित करने का प्रयास करेगा तो सबसे अधिक सिरदर्द होगा।


1
ज़रुरी नहीं। यह एक विशेषता के साथ किया जा सकता था (VB.NET में डिफ़ॉल्ट मापदंडों की तरह) और संकलक को संकलन समय पर बदल दिया है। प्राथमिक कारण C # डिज़ाइन लक्ष्य है।
मेहरदाद अफश्री

कंपाइलर को यह सुनिश्चित करना है कि डिफ़ॉल्ट पैरामीटर सामान्य बाधाओं को संतुष्ट करता है। साथ ही डिफ़ॉल्ट पैरामीटर एक सामान्य बाधा होगी क्योंकि विधि में टाइप पैरामीटर के बारे में बनाई गई किसी भी धारणा के लिए यह आवश्यक होगा कि कोई भी गैर-डिफ़ॉल्ट प्रकार का पैरामीटर उससे विरासत में मिले।
एंड्रयू हरे

@ और, डिफ़ॉल्ट पैरामीटर को सामान्य बाधा नहीं होना चाहिए। यदि यह C ++ में डिफ़ॉल्ट टेम्प्लेट मापदंडों की तरह अधिक व्यवहार करना था, तो ऑटोमैटोनिक की कक्षा में विस्तार करना यह पूरी तरह से ठीक होगा: MyTemplate <int, float> x = null क्योंकि T2 में कोई सामान्य बाधा नहीं है, इसलिए डिफ़ॉल्ट प्रकार के स्ट्रिंग के बावजूद फ़्लोट ठीक है । इस तरह डिफ़ॉल्ट टेम्पलेट पैरामीटर अनिवार्य रूप से MyTemplate <int> MyTemplate <int, string> के लिए आशुलिपि के रूप में लिखने के लिए "सिंटैक्टिकल चीनी" हैं।
टायलर लैंग

@ और, मैं इस बात से सहमत हूं कि C # कंपाइलर को यह सत्यापित करना चाहिए कि ऐसे डिफ़ॉल्ट टेम्पलेट पैरामीटर मौजूदा जेनेरिक बाधाओं को संतुष्ट करते हैं। सी # कंपाइलर पहले से ही क्लास की घोषणाओं में कुछ अनौपचारिक रूप से पुष्टि करता है, उदाहरण के लिए रीड के बेसगैनिक <टी, यू> क्लास और फिर मायगेंरिक "टी" जैसे "जहाँ: आईएसओइम्तेर्तेफेस" के रूप में एक सामान्य बाधा जोड़ें, एक त्रुटि के साथ संकलन करने में विफल रहेगा। डिफ़ॉल्ट टेम्प्लेट पैरामीटर को सत्यापित करना बहुत ही समान होगा: कंपाइलर एक वर्ग की घोषणा पर पुष्टि करता है और त्रुटि संदेश समान या बहुत समान हो सकता है।
टायलर लिंग

"यह लागू करने के लिए एक कठिन विशेषता होगी" यह बकवास है। इसे लागू करना तुच्छ होगा। टेम्पलेट बाधाओं के खिलाफ एक प्रकार को मान्य करने का काम कठिन नहीं होता है क्योंकि उम्मीदवार प्रकार फ़ाइल में एक अलग स्थान पर दिखाई देता है (अर्थात टेम्पलेट तात्कालिकता के बजाय टेम्पलेट में)।
मड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.