2010-09-11 12 views
54

मुझे इस प्रश्न से एक सहयोगी ने पूछा है कि क्या हमें हमेशा कक्षा में एक डिफ़ॉल्ट कन्स्ट्रक्टर शामिल करना चाहिए? यदि हां, तो क्यों? यदि नहीं, क्यों नहीं?क्या हमें कक्षा में हमेशा एक डिफ़ॉल्ट कन्स्ट्रक्टर शामिल करना चाहिए?

उदाहरण

public class Foo { 

    Foo() { } 

    Foo(int x, int y) { 
     ... 
    } 

} 

मैं भी विशेषज्ञों से इस पर कुछ रोशनी पाने के लिए दिलचस्पी है।

+16

सामान्य रूप से - केवल जब आवश्यक हो। –

+0

हाँ, मैं भी उत्सुक हूँ। मेरा प्रबंधक हमेशा मुझसे कहता है कि प्रतिबिंब के लिए इसकी आवश्यकता है, लेकिन मैं इसके बारे में कुछ भी नहीं कर सका, इसलिए मैं थोड़ा उलझन में हूं। –

उत्तर

83

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

public class Foo 
{ 
} 

है संकलक इस रूप में उत्पन्न होगा: जैसे ही

public class Foo 
{ 
    public Foo() { } 
} 

हालांकि, अगर आप अन्य निर्माता

public class Foo 
{ 
    public Foo(int x, int y) 
    { 
     // ... 
    } 
} 

संकलक नहीं रह जाएगा जोड़ने के रूप में स्वचालित रूप से आपके लिए डिफ़ॉल्ट कन्स्ट्रक्टर जेनरेट करें। यदि वर्ग पहले से ही दूसरे कोड में उपयोग किया जा रहा था जो डिफ़ॉल्ट कन्स्ट्रक्टर, Foo f = new Foo(); की उपस्थिति पर निर्भर था, तो वह कोड अब टूट जाएगा।

यदि आप नहीं चाहते हैं कि कोई डेटा प्रदान किए बिना कक्षा को प्रारंभ करने में सक्षम हो, तो आपको एक डिफ़ॉल्ट कन्स्ट्रक्टर बनाना चाहिए जो कि private है, इस तथ्य के बारे में स्पष्ट होना चाहिए कि आप कोई इनपुट डेटा के साथ निर्माण होने से रोक रहे हैं।

हालांकि, कई बार, जब यह एक डिफ़ॉल्ट कन्स्ट्रक्टर (चाहे सार्वजनिक या निजी) प्रदान करना आवश्यक हो। जैसा कि पहले उल्लेख किया गया था, कुछ प्रकार के क्रमिकरण के लिए एक डिफ़ॉल्ट कन्स्ट्रक्टर की आवश्यकता होती है। ऐसे समय भी होते हैं जब एक वर्ग में कई पैरामीटरयुक्त कन्स्ट्रक्टर होते हैं लेकिन उन्हें "निचले स्तर" प्रारंभिकरण की भी आवश्यकता होती है, इस मामले में एक निजी डिफ़ॉल्ट कन्स्ट्रक्टर का उपयोग किया जा सकता है जो पैरामीटरयुक्त कन्स्ट्रक्टर से बंधे होते हैं।

public class Foo 
{ 
    private Foo() 
    { 
     // do some low level initialization here 
    } 

    public Foo(int x, int y) 
     : this() 
    { 
     // ... 
    } 

    public Foo(int x, int y, int z) 
     : this() 
    { 
     // ... 
    } 
} 
+0

मुझे लगता है कि आप वहां कुछ 'सार्वजनिक' संशोधक गायब हैं (कक्षा के सदस्य डिफ़ॉल्ट रूप से 'निजी' हैं) ... –

+0

@ दैन ताओ: हाँ, मैं था। धन्यवाद @ एंथनी पेग्राम उन्हें मेरे लिए जोड़ने के लिए। –

+0

आपको कक्षा के नाम के बाद भी() नहीं होना चाहिए। उन्हें बाहर निकालें और आपके पास पर्याप्त कोड है जिसे आप संकलित करने का प्रयास कर सकते हैं और देख सकते हैं कि यह उत्तर गलत है, और डिफ़ॉल्ट कन्स्ट्रक्टर का उपयोग करने का प्रयास करने के परिणामस्वरूप "फू" में एक कन्स्ट्रक्टर नहीं होता है जो '0' तर्क लेता है " । –

20

कुछ चीजें (जैसे क्रमबद्धता) को एक डिफ़ॉल्ट कन्स्ट्रक्टर की आवश्यकता होती है। इसके बावजूद, एक डिफ़ॉल्ट कन्स्ट्रक्टर केवल तभी जोड़ा जाना चाहिए जब यह समझ में आता है।

उदाहरण के लिए, यदि Foo.X और Foo.Y गुण निर्माण के बाद अपरिवर्तनीय हैं तो एक डिफ़ॉल्ट निर्माता वास्तव में समझ में नहीं आता है। भले ही इसे 'खाली' फू के लिए उपयोग किया गया हो, फिर भी एक स्थिर Empty एक्सेसर अधिक खोजे जा सकेंगे।

+1

सीरियलाइजेशन को डिफ़ॉल्ट कन्स्ट्रक्टर की आवश्यकता नहीं है। यदि आपके पास एक वर्ग है जिसे आप क्रमबद्ध करना चाहते हैं, जिसके लिए एक डिफ़ॉल्ट कन्स्ट्रक्टर समझ में नहीं आता है, तो 'ISerializable' को लागू करें, और हस्ताक्षर' 'नाम 'के साथ एक कन्स्ट्रक्टर (' निजी' अगर मुहरबंद, 'संरक्षित' अन्यथा जोड़ें) क्लासनाम (SerializationInfo जानकारी, स्ट्रीमिंग कॉन्टेक्स्ट संदर्भ) 'जो 'ISerializable.GetObjectData' के कार्यान्वयन को प्रतिबिंबित करता है। –

12

मैं कहूंगा नहीं, निश्चित रूप से हमेशा नहीं है। मान लें कि आपके पास कुछ पाठक फ़ील्ड वाले वर्ग हैं जिन्हें कुछ मूल्यों के लिए प्रारंभ किया जाना चाहिए, और कोई उचित डिफ़ॉल्ट नहीं है (या आप वहां नहीं होना चाहते हैं)? इस परिदृश्य में मुझे नहीं लगता कि पैरामीटर रहित कन्स्ट्रक्टर समझ में आता है।

+4

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

0

ज्यादातर मामलों में एक डिफ़ॉल्ट कन्स्ट्रक्टर एक अच्छा विचार है। लेकिन चूंकि आप "हमेशा" शब्द का उपयोग करते हैं, इसलिए इसकी आवश्यकता केवल एक counterexample है। यदि आप फ्रेमवर्क देखते हैं, तो आपको बहुत कुछ मिल जाएगा। उदाहरण के लिए, System.Web.HttpContext।

2

हाँ आमतौर पर ज्यादातर मामलों में डिफ़ॉल्ट कन्स्ट्रक्टर लिखना बेहतर होता है।

आम तौर पर यदि आप कोई कन्स्ट्रक्टर निर्दिष्ट नहीं करते हैं, तो।नेट स्वचालित रूप से आपके लिए एक डिफ़ॉल्ट कन्स्ट्रक्टर बनाता है।

सीरियलाइजेशन को डिफ़ॉल्ट कन्स्ट्रक्टर की आवश्यकता है।

+0

सीरियलाइजेशन को डिफ़ॉल्ट कन्स्ट्रक्टर की आवश्यकता नहीं है।यदि आपके पास एक वर्ग है जिसे आप क्रमबद्ध करना चाहते हैं, जिसके लिए एक डिफ़ॉल्ट कन्स्ट्रक्टर समझ में नहीं आता है, तो 'ISerializable' को लागू करें, और हस्ताक्षर' 'नाम 'के साथ एक कन्स्ट्रक्टर (' निजी' अगर मुहरबंद, 'संरक्षित' अन्यथा जोड़ें) क्लासनाम (SerializationInfo जानकारी, स्ट्रीमिंग कॉन्टेक्स्ट संदर्भ) 'जो 'ISerializable.GetObjectData' के कार्यान्वयन को प्रतिबिंबित करता है। –

+0

प्वाइंट गिना गया। असल में मैं इसे जानता हूं, लेकिन आम तौर पर लोग सरल होना चाहते हैं। लेकिन आपने जवाब में एक बिंदु जोड़ा। धन्यवाद। – abhishek

+0

बस उत्सुक है, मेरे पास मेरी धारावाहिक कक्षा के अंदर एक सूची है। मैंने कन्स्ट्रक्टर नहीं जोड़ा और मुझे एक अपवाद मिला। जब मैंने कन्स्ट्रक्टर जोड़ा और कन्स्ट्रक्टर के अंदर मेरी सूची को तुरंत चालू किया, तो यह ठीक काम किया। बस उत्सुक, serialization मेरे मामले में एक डिफ़ॉल्ट कन्स्ट्रक्टर की आवश्यकता क्यों होगी? –

4

एक डिफ़ॉल्ट कन्स्ट्रक्टर होने के कारण यह एक अच्छा विचार है यदि यह ऐसी वस्तु रखने के लिए समझ में आता है।

यदि आप ऐसी वस्तु उत्पन्न करते हैं जो ऐसे कन्स्ट्रक्टर से वैध स्थिति में नहीं है, तो केवल एक चीज जो यह कर सकती है वह एक बग पेश कर रही है।

1

एक तरफ ध्यान दें, जब वर्ग के बजाय struct का उपयोग कर, ध्यान रखें कि हैं कि कोई रास्ता नहीं डिफ़ॉल्ट निर्माता बाहर छोड़ने के लिए, न ही यह यह अपने आप को परिभाषित करना संभव है, इसलिए जो कंस्ट्रक्टर्स आपके द्वारा निर्धारित की परवाह किए बिना के रूप में, यह सुनिश्चित कर लें कि संरचना की डिफ़ॉल्ट स्थिति (जब सभी चर उनके डिफ़ॉल्ट स्थिति (आमतौर पर मान प्रकारों के लिए 0, और संदर्भ प्रकारों के लिए शून्य) पर सेट होते हैं, तो संरचना के आपके कार्यान्वयन को तोड़ नहीं देंगे।

0

एक सामान्य प्रकार केवल तभी हो सकता है C# के साथ तत्काल (प्रतिबिंब के बिना) यदि उसके पास डिफ़ॉल्ट कन्स्ट्रक्टर है। इसके अलावा, new() सामान्य प्रकार की बाधा निर्दिष्ट की जानी चाहिए:

void Construct<T>() 
    where T : new() 
{ 
    var t = new T(); 
    ... 
} 

जेनेरिक प्रकार तर्क के रूप में एक प्रकार का उपयोग करके इस विधि को कॉल करना जिसमें संकलक त्रुटि में कोई डिफ़ॉल्ट कन्स्ट्रक्टर परिणाम नहीं है।

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

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