2012-05-31 11 views
18

अगर मैं इस तरह एक वर्ग है: मैं फिर से कारक कुछ स्तर परक्या कोई कन्स्ट्रक्टर दूसरे को लागू करता है तो कोई लाभ या कमी होती है?

public class Foo 
{ 
    public IEnumerable<Bar> Bars { get; set; } 

    public Foo() 
    { 
     Bars = new List<Bar>(); 
    } 
} 

वर्ग और एक माध्यमिक निर्माता जो इस तरह पहले एक को लागू करता है जोड़ें:

public class Foo 
{ 
    public IEnumerable<Bar> Bars { get; set; } 

    // some more properties were added 

    public Foo() 
    { 
     Bars = new List<Bar>(); 
    } 

    public Foo(string parameter): this() 
    { 
     .... some code here 
    } 
} 

मैं भी हो सकता था यह लिखा इस के समान:

public class Foo 
{ 
    public IEnumerable<Bar> Bars { get; set; } 

    // some more properties were added too 

    public Foo() 
    { 
     InitilizeFoo(); 
    } 

    public Foo(string parameter) 
    { 
     InitilizeFoo(); 
     .... some code here 
    } 

    private void InitializeFoo() 
    { 
     Bars = new List<Bar>(); 
    } 
} 

देखकर दोनों इस परिदृश्य में काम दृष्टिकोण, वहाँ एक फायदा है या एक दूसरे के ऊपर का उपयोग करने में दोष?

उत्तराधिकारी कंसट्रक्टर अधिक कुशल है और यह कोड तेजी से निष्पादित कर रहा है या क्या कोई कमी है जिसे मैं दूसरे कार्यान्वयन को और अधिक कुशल बनाने के बारे में नहीं जानता?

+1

मैं दोनों का उपयोग करता हूं। जब यह चेन कन्स्ट्रक्टर को एक साथ समझ में आता है, तो मैं करता हूं; लेकिन कभी-कभी (उदाहरण दिमाग में नहीं आ रहा है) मैं 'InitializeFoo()' विधि के साथ गया हूं और इसे सभी रचनाकारों से बुलाया है। – Nate

+0

अपवाद सुरक्षा केवल एक चीज के बारे में है जिसके बारे में मुझे चिंता होगी। –

उत्तर

28

एक कन्स्ट्रक्टर को एक और कन्स्ट्रक्टर कॉल करने में प्रमुख लाभों में से एक यह है कि आप केवल पढ़ने के लिए फ़ील्ड्स सेट कर सकते हैं, आप गैर-कन्स्ट्रक्टर विधि को कॉल करके ऐसा नहीं कर सकते हैं।

उदाहरण के लिए:

public class Foo 
{ 
    private readonly int myNumber; 

    public Foo() : this(42) 
    { 
    } 

    public Foo(int num) 
    { 
     myNumber = num; 
    } 
} 

प्रदर्शन बुद्धिमान, यह शायद कोई और अधिक या कम कुशल एक और विधि कॉल करने से एक और निर्माता कॉल करने के लिए है, लेकिन यह एक निर्माता एक और कॉल करने के लिए, और अधिक पठनीय है, मेरी राय में एक अलग, निजी विधि को कॉल करने के बजाय कन्स्ट्रक्टर जिसका एकमात्र बिंदु एक निर्माता द्वारा बुलाया जाना है।

निश्चित रूप से, अलग-अलग विधि होने पर स्थितियां हो सकती हैं, और यह निश्चित रूप से "गलत" नहीं है। चेनिंग कन्स्ट्रक्टर ज्यादातर उपयोगों के लिए बहुत से लोगों को बेहतर पढ़ता है, और कोई नकारात्मक प्रदर्शन प्रभाव नहीं होता है।

अद्यतन: मैं हर तरह की 10000000 पुनरावृत्तियों प्रदर्शन (बनाम निजी प्रारंभ विधि श्रृंखलित) और परिणाम इतने करीब वे लगभग अप्रभेद्य थे:

Initializer Method took: 84 ms for 10,000,000 iterations, 8.4E-06 ms/each. 
Chained Constructors took: 81 ms for 10,000,000 iterations, 8.1E-06 ms/each. 

तो सच में, प्रदर्शन के लिहाज से वहाँ लगभग है कोई किसी भी तरह से लाभ। मुख्य लाभ जंजीर रचनाकारों के साथ है, आप readonly फ़ील्ड सेट कर सकते हैं, और ज्यादातर मामलों में यह अधिक पठनीय है।

+0

त्वरित प्रतिक्रिया के लिए बहुत बहुत धन्यवाद। मैं पूरी तरह से सहमत हूं कि यह और अधिकांश डिज़ाइन अवरोध स्थितित्मक हैं और कभी-कभी यह केवल एक और तरीके से बेहतर काम करता है। मेरी मुख्य चिंता प्रदर्शन के संबंध में थी, संकलन या निष्पादन समय को प्रभावित करती थी। आपने इसे अच्छी तरह से संबोधित किया है, बहुत बहुत धन्यवाद। – Nope

+2

कभी भी! कुछ भी के रूप में, एक छोटे से परीक्षण लिखना और सिस्टम का उपयोग करना वास्तव में आसान होगा। डायग्नोस्टिक्स। स्टॉपवॉच() प्रत्येक के कुछ मिलियन पुनरावृत्तियों को मापने के लिए ... –

+0

हमें उस काम में कोई समस्या थी जिसके लिए मैंने तय किया गया फिक्स बस था ': यह()'। मैं फिक्स और संभावित दक्षता के मुद्दों के बारे में थोड़ा चिंतित था। मैंने इसके बजाय एक त्वरित परीक्षण लिखने के बारे में कभी सोचा नहीं। यह बात बताने के लिए धन्यवाद। मैं निश्चित रूप से यह कोशिश करूँगा ... काम के बाद :)। – Nope

4

कुंजी डुप्लिकेट कोड की मात्रा को कम करने के लिए है। इस मामले में, पैरामीटरयुक्त कन्स्ट्रक्टर से बेस कन्स्ट्रक्टर को कॉल करने से दोनों को अपडेट करने के बाद बाद में एक बग जोड़ने की संभावना कम हो जाती है।

+1

यदि दोनों रचनाकार एक ही 'इनिट' विधि को कॉल करते हैं तो यह समस्या पहले ही संबोधित है। ऐसा प्रतीत होता है कि ओपी कोड की तुलना कर रहा है। – Servy

6

चेनिंग कन्स्ट्रक्टर एसआरपी और कार्यक्रम प्रवाह को लागू करने का एक अच्छा तरीका है। एक स्टैंडअलोन Initialize() फ़ंक्शन के अंदर प्रारंभिक कोड छिपाने से ऑब्जेक्ट लाइफसाइक्ल में अन्य स्थितियां हो सकती हैं, जहां आप इसे "प्रारंभ करना" भी चाहते हैं; शायद अगर आप जल्दी से जल्दी और आलसी शुरू करने में सक्षम होना चाहते हैं- इसे शुरू करें। लेकिन यदि जीवनशैली में एकमात्र वैध समय उस कार्यक्षमता को निष्पादित करने के लिए तत्काल है, और प्रारंभिकता अलग-अलग चरणों का एक अच्छी तरह परिभाषित सेट है जिसे क्रम में लेने की आवश्यकता है, तो चेनिंग इसे सुविधाजनक बनाता है।

+0

मैं एसआरपी के बावजूद कभी नहीं, यह एक बहुत अच्छा मुद्दा है। – Nope

3

यदि आप अपना ऑब्जेक्ट रीसेट करना चाहते हैं तो प्रारंभिक() फ़ंक्शन होने का लाभ है - आप ऑब्जेक्ट को फिर से बनाने के बजाय & को हटाने के बजाय फिर से इनिट फ़ंक्शन को कॉल कर सकते हैं।

+2

+1। क्यों शुरूआत दृष्टिकोण उपयोगी हो सकता है। नोट: मैं कक्षा से इसे टालने के लिए फिर से डिजाइन करने का प्रयास करूंगा - अगर उदाहरण कई अन्य वस्तुओं के बीच साझा किया गया है तो किसी को ऑब्जेक्ट की स्थिति में इस तरह के महत्वपूर्ण परिवर्तन के बारे में सूचित करने के लिए समन्वय कोड प्रदान करने की आवश्यकता हो सकती है। –

+0

अच्छा है। यह तय करते समय कि कौन सा कार्यान्वयन करना है, यह बहुत उपयोगी है। धन्यवाद। – Nope

2

मैं यह कह के लिए जला दिया जा सकता है, लेकिन मैं इस मामले में डिफ़ॉल्ट पैरामीटर का उपयोग कर पसंद करते हैं:

public Foo(string parameter = null) 
{ 

} 

मैं ऐसे मामलों में जहां मैं 10 की थी लिया है - 15 वैकल्पिक पैरामीटर और 15 होने विभिन्न कंस्ट्रक्टर्स नहीं था एक मेरी राय में सुरुचिपूर्ण समाधान। मुझे लगता है कि डिफ़ॉल्ट पैरामीटर केवल 4.0 फ्रेमवर्क में पुन: प्रस्तुत किए गए थे।

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