2009-05-14 10 views
27

मैं सोच रहा था, सी # में एक नई वस्तु बनाने का पसंदीदा तरीका क्या है?सी # में वस्तुओं का निर्माण करने का पसंदीदा तरीका क्या है? निर्माता पैरामीटर या गुण?

New Person("name", 24); 

या

New Person() { Name = "name", Age = 24 }; 

यह स्वाद का मामला है या एक अच्छा है:

public class Person 
{ 
    private string name; 
    private int age; 

    //Omitted.. 
} 

मैं इसे उपयोग करने के लिए बनाना चाहिए:

एक व्यक्ति वर्ग ले लो एक दूसरे के ऊपर उपयोग करने का कारण?

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

क्या मैं उसमें सही हूँ?

Person p = new Person(); 
p.Name = "name"; 
p.Age = 24; 

तुम भी निर्माता जो सभी गुण आप सेट करना चाहते initalize नहीं हो सकता है पर निर्भर करता है नहीं कर रहे हैं:

+2

यह प्रभावी रूप से http://stackoverflow.com/questions/830657 –

उत्तर

39

पसंदीदा तरीका आपके डिजाइन पर निर्भर करता है।

कन्स्ट्रक्टर गुण उन वस्तुओं के लिए हैं जिनके लिए आपके ऑब्जेक्ट को सही ढंग से निर्मित करने के लिए आवश्यक है। ऐसा कहने के लिए, किसी भी गुण को ऑब्जेक्ट को प्रारंभ करने के लिए होना चाहिए ताकि कन्स्ट्रक्टर में होना आवश्यक हो (आप आमतौर पर आंशिक रूप से इंटिलाइज्ड ऑब्जेक्ट नहीं चाहते हैं जब तक कि कन्स्ट्रक्टर को तब तक बुलाया न जाए जब तक आप कोई फैक्ट्री या बिल्डर पैटर्न नहीं बनाते और निर्माता सभी कारखाने/निर्माता से छिपा हुआ है)।

संपत्ति intializers एक निर्माता है कि आपका विशेष उपयोग के मामले के लिए आवश्यक है, लेकिन वस्तु initialised पर विचार किया जाएगा के लिए की आवश्यकता नहीं है के बाद अतिरिक्त विन्यास के लिए सबसे अच्छा कर रहे हैं।

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

Person johnDoe = new Person("John Doe", 24) { Address = "42 Adams Street" }; 
+0

यह एक बहुत अच्छा तर्क है जो यह समझने में मदद करता है कि आवेदन कब करें। धन्यवाद! – Peterdk

+0

मैं मार्क Gravell का जवाब पढ़ने के साथ-साथ की सिफारिश (http://stackoverflow.com/a/863064/23234) है, जो कुछ वैकल्पिक परिदृश्यों है कि वास्तविक उपयोग करता है, जहां मैं प्रस्तुत अधिक आदर्श दृष्टिकोण अन्य सीमाओं के कारण प्रासंगिक नहीं है पर देखने के प्रदान करता है। –

2

दूसरा तरीका गुण मैन्युअल स्थापना के लिए बस वाक्यात्मक चीनी है।

यदि आपकी कक्षा में एक निर्माता है जिसके लिए इन दो पैरामीटर की आवश्यकता है, तो आप उस कन्स्ट्रक्टर को स्पष्ट रूप से कॉल करने के लिए चारों ओर नहीं पहुंचते हैं।

12

यह वास्तव में परिदृश्य पर निर्भर करता है। संपत्ति दृष्टिकोण में बहुत सी सुविधा है, जिसमें आपको कन्स्ट्रक्टर में असाइनमेंट को डुप्लिकेट करने की आवश्यकता नहीं है। इसके अलावा, अधिकांश डेटा-बाइंडिंग परिदृश्य नई ऑब्जेक्ट्स बनाने में सक्षम होना पसंद करते हैं, जिसके लिए वे आमतौर पर पैरामीटर रहित कन्स्ट्रक्टर का उपयोग करते हैं, इसलिए यह एक बड़ा फायदा है।

हालांकि, अपरिवर्तनीय प्रकारों के लिए, कन्स्ट्रक्टर दृष्टिकोण एकमात्र समझदार विकल्प है। दिलचस्प बात यह है कि (शायद) सी # 4.0 में नामित/वैकल्पिक पैरामीटर अपरिवर्तनीय प्रकारों के लिए ऑब्जेक्ट इनलाइलाइज़र के समान कुछ अनुमति देते हैं - see here

कन्स्ट्रक्टर दृष्टिकोण नियंत्रण ढांचे के उलटने के लिए भी बहुत लोकप्रिय है, क्योंकि यह स्पष्ट रूप से विज्ञापित करता है कि उस वर्ग को कार्य करने के लिए क्या आवश्यक है।

आपको मिश्रण और मिलान करने की आवश्यकता हो सकती है, लेकिन आमतौर पर कन्स्ट्रक्टर-शैली की तुलना में अधिक संपत्ति-शैली।

+2

का सी # संस्करण है - केवल पढ़ने वाले फ़ील्ड केवल कन्स्ट्रक्टर कोड द्वारा सेट किए जा सकते हैं। – Dario

5

कन्स्ट्रक्टर में मानों को सेट करना, उन गुणों को अनिवार्य बनाता है, इसलिए इसका मतलब है कि आप उन गुणों को सेटिंग के बिना एक नया उदाहरण नहीं बना सकते हैं। कुछ स्थितियों में यह बेहतर है, अन्य परिस्थितियों में यह prefferable नहीं है।

+0

यह सच है, हालांकि structs के लिए आप निश्चित रूप से सेटिंग अनिवार्य नहीं कर सकते हैं। – Noldorin

+0

दरअसल, लेकिन यह है कि क्योंकि एक struct एक मूल्य के प्रकार है, और हमेशा एक (डिफ़ॉल्ट) मूल्य है, भले ही यह प्रारंभ नहीं किया गया है,। –

0

इस प्रश्न पर मेरा मुख्य विचार 1 है) ऑब्जेक्ट तत्काल होने पर तत्काल इकाई को कितना डेटा होगा और 2) कक्षा को कैसे समेकित किया जाना चाहिए? यदि, एक बार सेट हो जाने पर, गुणों को कम से कम किसी भी बाहरी संस्थाओं के कारण बदलने में सक्षम नहीं होना चाहिए) तो मैं कन्स्ट्रक्टर का उपयोग करूंगा, क्योंकि कन्स्ट्रक्टर किसी भी पठनीय गुणों के साथ-साथ किसी भी पढ़ने/लिखने वाले गुणों को सेट कर सकता है।

यह भी याद रखें कि, किसी भी अन्य विधि की तरह, आपके कन्स्ट्रक्टर को ओवरलोड किया जा सकता है, ताकि आप उन गुणों को प्रारंभ करने के लिए कई तरीकों को सेट कर सकें।

सामान्यतः, मैं रचनाकारों का उपयोग करता हूं, लेकिन कई बार जब मैं गुणों को मैन्युअल रूप से सेट करता हूं। सही समस्या के लिए सही उपकरण का प्रयोग करें।

7

मैं हमेशा आधार है कि आप एक निर्माता जिसके लिए उस वस्तु एक मान्य राज्य में मौजूद अनिवार्य हैं करने के लिए मूल्यों को पास करना चाहिए पर काम करते हैं।

आप उदाहरण में आप कह सकते हैं कि नए व्यक्ति को एक उम्र के बिना मौजूद नहीं कर सकते हैं ताकि contructor करने के लिए पारित किया जाना चाहिए।

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

+1

+1: वस्तुओं हमेशा निर्माण के बाद एक वैध राज्य में और प्रत्येक विधि कॉल के बाद छोड़ दिया जाना चाहिए, ताकि तरीकों चल रहा है, केवल उनके तर्कों से पहले अपने स्वयं के वस्तु के राज्य को मान्य करने की जरूरत नहीं है। – palm3D

2

मेरी राय में, आपको पहले यह तय करना चाहिए कि किसी व्यक्ति को व्यक्ति क्या बनाता है। किसी व्यक्ति के लिए सही ढंग से तत्काल होने के लिए व्यक्ति के गुण क्या हैं। किसी व्यक्ति के लिए न्यूनतम आवश्यकताएं क्या हैं।

हमेशा न्यूनतम आवश्यकताओं के साथ एक कन्स्ट्रक्टर होना चाहिए।

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

मुझे पता है कि ऑब्जेक्ट प्रारंभकर्ता बहुत सुविधाजनक हैं। अन्य तंत्र भी वस्तु में एक खाली कन्स्ट्रक्टर की आवश्यकता हो सकती है।

लेकिन मुझे नहीं लगता कि यह बहुत समझ में आता है कि आप बिना किसी नाम के व्यक्ति बना सकते हैं।

4

कुछ विचार:

  1. आप ऑब्जेक्ट initializers उपयोग करने के लिए सार्वजनिक संपत्तियों की जरूरत है। तो अगर ऐसा कुछ है जिसे आप बेनकाब नहीं करना चाहते हैं, तो आपको उन्हें कन्स्ट्रक्टर पैरामीटर द्वारा प्रारंभ करना होगा।

  2. आप आईएल जाँच हैं, तो आप ऑब्जेक्ट प्रारंभकर्ता मिलेगा "परमाणु" नहीं है। आप (नहीं है कि मैं सलाह देते हैं, सिर्फ एक उदाहरण) इस तरह कोड लिखते हैं:

    using (p = New Person() {Name = GetName(), Age = GetAge()}) 
    { 
        //blah, blah 
    } 
    

    अगर वहाँ GetAge() में एक अपवाद है, तो आप एक भ्रष्ट राज्य में Person का एक उदाहरण का निर्माण करेगा। इससे भी बदतर, आप कभी भी उपयोग करने वाले दायरे में प्रवेश नहीं कर सकते हैं और उस उदाहरण को आप कल्पना नहीं करेंगे जैसा कि आप कल्पना करेंगे।

+0

मुझे यह पसंद है कि आपने बताया है कि यह परमाणु नहीं है। स्पष्ट जब आप इसे देखते हैं, और मुझे नहीं लगता कि आप इसे रख दिया है मैं कोड लिखने चाहते हैं, लेकिन अगर मैं किसी और के कोड पढ़ रहा था मुझे नहीं लगता कि मैं इस पर उठाया गया है करेगा। –

0

सेटिंग्स के लिए मैन्युअल रूप से गुणों के लिए, उन्हें सार्वजनिक घोषित करना होगा, और आप कक्षा के सदस्यों को निजी होना चाहते हैं। इस मामले में कन्स्ट्रक्टर जाने का तरीका है, या उन्हें प्राप्त करने/सेट करने के लिए विधियों को लिखने का तरीका है।

0

मैं संपत्ति intializers के साथ एक बहुत ही सरल निर्माता पसंद करते हैं। मुझे लगता है कि यह अधिक स्पष्ट कोड की ओर जाता है। कन्स्ट्रक्टर को पास करने वाला एकमात्र डेटा वह जानकारी है जो मैं नहीं चाहता कि वर्ग बनने के बाद मेरी कक्षा का उपयोगकर्ता बदल जाए।

0

असली मुद्दा आता है जब आप स्तरों/परतों के माध्यम से वस्तु गुजरती हैं। उदाहरण के लिए आप एक व्यक्ति वस्तु बनाते हैं और एक webservice के माध्यम से गुजरते हैं। somepoint पर वेब सेवा deserialize की कोशिश करता है और दृष्टांत के लिए और अगर वहाँ एक पैरामीटर निर्माताओं के लिए आवश्यक है, तो आप त्रुटि आ सकती है की कोशिश करता है! क्योंकि webservices पहले ऑब्जेक्ट बनाता है और फिर मान निर्दिष्ट करता है।

तो अगर मैं एक डाटामैडेल (पीओसीओ प्रकार) है तो मुझे पैरामीटर रहित नियंत्रक पसंद करेंगे, जिसे टायरों से गुज़रने की आवश्यकता है।

अन्य कारणों से नियंत्रक पैरामीटर सबसे अच्छा तरीका है (अनिवार्य फ़ील्ड के लिए)। खासकर जब कक्षा को बाहरी वस्तुओं या असेंबली के लिए एक इयरफेस के रूप में प्रदान करते हैं।

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

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