C # में एक नया () अवरोध क्यों है लेकिन कोई अन्य समान बाधा नहीं है?


19

C # जेनरिक में, हम एक प्रकार के पैरामीटर के Tलिए एक डिफ़ॉल्ट निर्माणकर्ता के लिए एक बाधा की घोषणा कर सकते हैं , कह कर where T : new()। हालांकि, इस तरह की कोई अन्य बाधाएं मान्य नहीं हैं - new(string)उदाहरण के लिए, आदि।

भाषा के डिजाइन और / या कार्यान्वयन के दृष्टिकोण से, इसका कारण क्या है?

क्या कंस्ट्रक्टर्स के काम करने के तरीके में कुछ ऐसा है या जिस तरह से सिस्टम लागू किया गया है कि यह मना करता है (या कम से कम यह कठिन है)? यदि ऐसा है, तो ये क्या है? मैंने कहीं पढ़ने याद है कि default(T)वास्तव में करने के लिए संकलित new T()के लिए T : struct। क्या यह इससे संबंधित है, हो सकता है?

या यह केवल एक डिजाइन निर्णय है जो भाषा को बहुत जटिल बनाने से बचने के लिए किया गया है?


new(string)एक डिफ़ॉल्ट निर्माता बाधा नहीं है। आपका प्रश्न यह कहने के लिए समान है कि "विशिष्ट निर्माण हस्ताक्षरों की आवश्यकता क्यों नहीं है?" बहुत संभावना है क्योंकि इस तरह की बाधा विशेष रूप से उपयोगी नहीं होगी।
रॉबर्ट हार्वे

3
@RobertHarvey हाँ, यह बिल्कुल वही है जो मैं कह रहा हूँ। मैं अनिवार्य रूप से पूछ रहा हूं कि क्या कुछ ऐसा है जो डिफ़ॉल्ट निर्माणकर्ताओं को विशेष कार्यान्वयन-वार बनाता है या यदि यह शामिल करने के लिए सिर्फ एक मनमाना विकल्प था और अन्य नहीं।
थियोडोरोस चट्जीगानियाकिस

डिफ़ॉल्ट निर्माता कुछ विशिष्ट और महत्वपूर्ण तरीकों से उपयोगी होते हैं। उदाहरण के लिए, वे एक प्रकार को आसानी से क्रमबद्ध बनाते हैं।
राबर्ट हार्वे

6
विशिष्ट ctor हस्ताक्षर उपयोगी हो सकते हैं। उदाहरण के लिए, यदि आपका टाइप वैरिएबल संग्रह <T> T के एक ctor (संग्रह <T>) के साथ विवश है, तो आप जानते हैं कि आप एक और दिए गए नए संग्रह का निर्माण कर सकते हैं। क्या यह उपयोगिता अतिरिक्त जटिलता के लायक है, हालांकि, एक सवाल है।
फॉशी

जवाबों:


5

एक आधिकारिक जवाब के लिए, मैं आपको कुछ साल पहले स्टैकऑवरफ्लो पर उस सवाल के एरिक लिपर्ट के जवाब का उल्लेख करूंगा , जिसका एक टुकड़ा संक्षेप में नीचे उद्धृत किया गया है।

हालाँकि, इस विशिष्ट मामले में मैं आपको निश्चित रूप से कुछ कारण दे सकता हूं कि भाषा के भविष्य के संस्करण के लिए एक संभावित सुविधा के रूप में अगर यह एक डिजाइन बैठक में आया तो मैं इस फीचर को आगे बढ़ाऊंगा।

...

मैं कहता हूं कि हमें या तो पूरी सुविधा करनी चाहिए या इसे बिल्कुल नहीं करना चाहिए। यदि विशेष रचनाकारों के प्रकारों को प्रतिबंधित करने में सक्षम होना महत्वपूर्ण है, तो चलो पूरी सुविधा करते हैं और सामान्य रूप से सदस्यों के आधार पर प्रकारों को प्रतिबंधित करते हैं, न कि केवल निर्माणकर्ताओं को।


2
वह उद्धरण, जो संदर्भ से बाहर है, बहुत भ्रामक है। यह बताता है कि एरिक ने सोचा कि माइक्रोसॉफ्ट को "सभी तरह से चले जाना चाहिए", जो कि उसकी स्थिति बिल्कुल भी नहीं है। वह, वास्तव में, प्रस्तावित सुविधा के खिलाफ है।
राबर्ट हार्वे

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

@TheodorosChatzigiannakis: क्यों तुम आग नहीं है Telerik के Decompiler और अपने आप के लिए यह पता लगाने?
रॉबर्ट हार्वे

2
@RobertHarvey मुझे नहीं लगता कि यह उसके लिए बिल्कुल एक स्थिति का सुझाव देता है, लेकिन मैंने उसकी स्थिति पर जोर देने के लिए एक अतिरिक्त उद्धरण शामिल किया है।
क्रिस हैनॉन

1
हम्म, एफ # में एक प्रकार की बाधा डालने के लिए अधिक अग्रिम तरीके हैं , जैसे संकलित समय की जाँच करना यदि किसी वर्ग के पास ऑपरेटर है। शायद, F # को बहुत सख्त प्रकार की जाँच के कारण C # से अधिक शक्तिशाली बाधा प्रणाली की आवश्यकता है। बहरहाल, यह भाषा .Net फ्रेमवर्क पर वर्ग को बनाए रखने के लिए एक उन्नत तरीके को लागू करने में सक्षम है।
ओनेसिमुसनबाउंड

16

विघटनकारी (रॉबर्ट हार्वे के सुझाव के अनुसार) ने किसी को भी दिलचस्पी लेने के लिए निम्न उपज दी। यह विधि:

static T GenericMake<T>()
    where T : new()
{
    return new T();
}

जाहिर है, जब संकलित, यह हो जाता है:

private static T GenericMake<T>()
    where T : new()
{
    T t;
    T t1 = default(T);
    if (t1 == null)
    {
        t = Activator.CreateInstance<T>();
    }
    else
    {
        t1 = default(T);
        t = t1;
    }
    return t;
}
  • यदि Tएक मूल्य प्रकार है, new()बन जाता है default(T)
  • यदि Tएक संदर्भ प्रकार है, तो new()प्रतिबिंब का उपयोग करके काम करता है। Activator.CreateInstance()आंतरिक रूप से कहता है RuntimeType.CreateInstanceDefaultCtor()

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


4
दिलचस्प। default(T) मूल्य प्रकारों के लिए डुप्लिकेट कॉल क्यों ?
अवनर शाहर-काश्तन

2
@ AvnerShahar-Kashtan मुझे नहीं पता। यह tचर की तरह संकलन / विघटन प्रक्रिया की एक कलाकृति हो सकती है (जिसे नेस्टेड returnस्टेटमेंट द्वारा प्रतिस्थापित किया जा सकता है )।
थियोडोरोस चट्जीगानियाकिस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.