2010-09-07 12 views
98

ऐसा लगता है कि सी # 3.0 ऑब्जेक्ट प्रारंभकर्ता सिंटैक्स एक पैरामीटर रहित कन्स्ट्रक्टर मौजूद होने पर कन्स्ट्रक्टर में कोष्ठक की खुली/करीबी जोड़ी को बाहर करने की अनुमति देता है। उदाहरण:सी # 3.0 ऑब्जेक्ट प्रारंभकर्ता कन्स्ट्रक्टर को वैकल्पिक क्यों हैं?

var x = new XTypeName { PropA = value, PropB = value }; 

के रूप में विरोध करने के लिए:

var x = new XTypeName() { PropA = value, PropB = value }; 

मैं उत्सुक हूँ क्यों निर्माता खोलने/बंद कोष्ठक जोड़ी वैकल्पिक यहाँ XTypeName के बाद है?

+7

एक तरफ के रूप में, हमने इसे पिछले सप्ताह एक कोड समीक्षा में पाया: var list = new list {}; अगर कुछ दुर्व्यवहार किया जा सकता है ... – blu

+0

@blu यही कारण है कि मैं इस सवाल से पूछना चाहता था। मैंने हमारे कोड में असंगतता देखी। सामान्य रूप से असंगतता मुझे परेशान करती है इसलिए मैंने सोचा कि मैं देखता हूं कि वाक्यविन्यास में वैकल्पिकता के पीछे कोई अच्छा तर्क था या नहीं। :) –

+0

संभावित डुप्लिकेट [ऑब्जेक्ट प्रारंभकर्ता और कन्स्ट्रक्टर के बीच क्या अंतर है?] (Http://stackoverflow.com/questions/740658/whats-the-difference-between-an-object-initializer-and-a- कन्स्ट्रक्टर) –

उत्तर

130

This question was the subject of my blog on September 20th 2010। जोश और चाड के जवाब ("वे कोई मूल्य नहीं जोड़ते हैं, इसलिए उन्हें क्यों आवश्यकता है?" और "अनावश्यकता को खत्म करने के लिए") मूल रूप से सही हैं। मांस को थोड़ा और अधिक करने के लिए:

ऑब्जेक्ट प्रारंभकर्ताओं की "बड़ी सुविधा" के हिस्से के रूप में आपको तर्क सूची को विस्तारित करने की सुविधा की सुविधा "शर्करा" सुविधाओं के लिए हमारी बार से मुलाकात की।कुछ बिंदुओं को हम पर विचार:

  • डिजाइन और विनिर्देश लागत कम
  • हम बड़े पैमाने पर पार्सर कोड है कि वस्तु निर्माण वैसे भी संभालती बदलते होने के लिए जा रहे थे था, पैरामीटर सूची वैकल्पिक बनाने की अतिरिक्त विकास लागत बड़ी सुविधा
  • की तुलना में बड़ी नहीं थी, परीक्षण बोझ बड़ी सुविधा
  • की तुलना में अपेक्षाकृत छोटा था, दस्तावेज़ीकरण बोझ अपेक्षाकृत कम था ..
  • रखरखाव बोझ छोटा होने की उम्मीद थी; मुझे इस सुविधा में रिपोर्ट किए जाने के बाद के वर्षों में रिपोर्ट की गई किसी भी बग को याद नहीं है।
  • सुविधा इस क्षेत्र में भविष्य की सुविधाओं के लिए तत्काल स्पष्ट जोखिम उत्पन्न नहीं करती है। (आखिरी चीज जो हम करना चाहते हैं वह अब एक सस्ती, आसान सुविधा बनाती है जो भविष्य में एक और अधिक आकर्षक सुविधा को कार्यान्वित करना अधिक कठिन बनाती है।)
  • सुविधा में व्याख्यात्मक, व्याकरणिक या अर्थपूर्ण विश्लेषण के लिए कोई नई अस्पष्टता नहीं है भाषा। जब आप टाइप कर रहे हों तो आईडीई के "इंटेलिसेन्स" इंजन द्वारा किए गए "आंशिक कार्यक्रम" विश्लेषण के लिए इसमें कोई समस्या नहीं है। और इसी तरह।
  • सुविधा बड़ी वस्तु प्रारंभिक सुविधा के लिए एक आम "मीठा स्थान" हिट करती है; आम तौर पर यदि आप किसी ऑब्जेक्ट प्रारंभकर्ता का उपयोग कर रहे हैं तो यह ठीक है क्योंकि ऑब्जेक्ट का निर्माता आपको इच्छित गुण सेट करने की अनुमति देता है। ऐसी वस्तुओं के लिए यह बहुत आम है कि वे "संपत्ति बैग" हों जिनके पास पहले स्थान पर सीटीआर में कोई पैरामीटर नहीं है।

क्यों तो आप भी खाली कोष्ठकों करता है कि नहीं एक ऑब्जेक्ट प्रारंभकर्ता है एक वस्तु निर्माण अभिव्यक्ति की डिफ़ॉल्ट निर्माता कॉल में वैकल्पिक नहीं किया?

ऊपर दिए गए मानदंडों की सूची पर एक और नज़र डालें। उनमें से एक यह है कि परिवर्तन किसी कार्यक्रम के शब्दावली, व्याकरणिक या अर्थपूर्ण विश्लेषण में कोई नई अस्पष्टता नहीं पेश करता है।

class P 
{ 
    class B 
    { 
     public class M { } 
    } 
    class C : B 
    { 
     new public void M(){} 
    } 
    static void Main() 
    { 
     new C().M(); // 1 
     new C.M(); // 2 
    } 
} 

लाइन 1, एक नया सी बनाता है डिफ़ॉल्ट निर्माता कहता है, और फिर नई वस्तु पर उदाहरण विधि एम कॉल: अपने प्रस्तावित परिवर्तन एक अर्थगत विश्लेषण अस्पष्टता को पेश करता है। लाइन 2 बीएम का एक नया उदाहरण बनाता है और इसके डिफ़ॉल्ट कन्स्ट्रक्टर को कॉल करता है। यदि लाइन 1 पर कोष्ठक वैकल्पिक थे तो लाइन 2 संदिग्ध होगा। हमें अस्पष्टता को हल करने के नियम के साथ आना होगा; हम इसे त्रुटि नहीं बना सकते क्योंकि यह एक तोड़ने वाला परिवर्तन होगा जो एक मौजूदा कानूनी सी # प्रोग्राम को टूटे हुए प्रोग्राम में बदल देगा।

इसलिए नियम बहुत जटिल होना चाहिए: अनिवार्य रूप से कि ब्रांड्स केवल उन मामलों में वैकल्पिक हैं जहां वे अस्पष्टताएं नहीं पेश करते हैं। हमें उन सभी संभावित मामलों का विश्लेषण करना होगा जो अस्पष्टताएं पेश करते हैं और फिर उन्हें पहचानने के लिए कंपाइलर में कोड लिखते हैं।

उस प्रकाश में, वापस जाएं और मुझे बताई गई सभी लागतों को देखें। उनमें से कितने बड़े हो गए हैं? जटिल नियमों में बड़े डिजाइन, spec, विकास, परीक्षण और दस्तावेज़ीकरण लागत है। जटिल नियम भविष्य में सुविधाओं के साथ अप्रत्याशित बातचीत के साथ समस्याओं का कारण बनने की अधिक संभावना है।

सभी के लिए क्या?एक छोटा सा ग्राहक लाभ जो भाषा के लिए कोई नई प्रतिनिधित्व शक्ति नहीं जोड़ता है, लेकिन पागल कोने के मामलों को जोड़ता है, जो कुछ गरीब असुरक्षित आत्मा में "गेटचा" चिल्लाता है। इस तरह की विशेषताएं तुरंत काट लें और "यह कभी नहीं करें" सूची डालें।

आपने उस विशेष अस्पष्टता को कैसे निर्धारित किया?

वह तुरंत स्पष्ट था; जब मैं बिंदीदार नाम की अपेक्षा करता हूं तो यह निर्धारित करने के लिए मैं सी # में नियमों से काफी परिचित हूं।

एक नई सुविधा पर विचार करते समय आप कैसे निर्धारित करते हैं कि यह किसी अस्पष्टता का कारण बनता है या नहीं? हाथ से, औपचारिक प्रमाण द्वारा, मशीन विश्लेषण द्वारा, क्या?

सभी तीन। अधिकतर हम ऊपर की तरफ से spec और नूडल देखते हैं, जैसा कि मैंने ऊपर किया था। उदाहरण के लिए, मान लीजिए हम "frob" कहा जाता है सी # के लिए एक नया उपसर्ग ऑपरेटर जोड़ना चाहते थे:

x = frob 123 + 456; 

(अद्यतन: frob पाठ्यक्रम await की है, विश्लेषण यहां अनिवार्य रूप से विश्लेषण है कि डिजाइन टीम के माध्यम से जब जोड़ने के लिए चला गया है await।)

"फ्रोब" यहां "नया" या "++" जैसा है - यह किसी प्रकार की अभिव्यक्ति से पहले आता है। हम वांछित प्राथमिकता और सहयोगीता का काम करेंगे और फिर, जैसे प्रश्न पूछना शुरू करें "क्या होगा यदि प्रोग्राम में पहले से ही एक प्रकार, फ़ील्ड, प्रॉपर्टी, इवेंट, विधि, स्थिर, या फ्रोब नामक स्थानीय है?" यही कारण है कि तुरंत तरह के मामलों के लिए नेतृत्व करेंगे:

frob x = 10; 

इसका मतलब यह है "x = 10 के परिणाम पर frob आपरेशन करते हैं, या के प्रकार frob बुलाया एक्स एक चर बनाने और इसे करने के लिए 10 आवंटित?" (या, यदि frobbing एक चर पैदा करता है, यह frob x करने के लिए 10 में से एक काम हो सकता है। सब के बाद, *x = 10; पार्स करके कानूनी है अगर xint* है।)

G(frob + x) 

इसका मतलब यह "एकल का परिणाम frob करता है एक्स पर प्लस ऑपरेटर "या" एक्स अभिव्यक्ति फ्रोब एक्स "में जोड़ें?

और इसी तरह। इन अस्पष्टताओं को हल करने के लिए हम हेरिस्टिक्स पेश कर सकते हैं। जब आप कहते हैं "var x = 10;" यह संदिग्ध है; इसका अर्थ यह हो सकता है कि "एक्स के प्रकार का अनुमान लगाएं" या इसका अर्थ यह हो सकता है कि "x प्रकार का var var" है। तो हमारे पास एक ह्युरिस्टिक है: हम पहले var नाम के प्रकार को देखने का प्रयास करते हैं, और केवल तभी जब कोई अस्तित्व में नहीं है तो हम x के प्रकार का अनुमान लगाते हैं।

या, हम वाक्यविन्यास बदल सकते हैं ताकि यह संदिग्ध न हो। जब वे सी # 2.0 तैयार किया गया है कि वे इस समस्या थी: "के साथ तर्क एक्स उपज विधि कॉल"

yield(x); 

"पुनरावर्तक में उपज एक्स" क्या दुर्भावनापूर्ण या इसे

yield return(x); 

यह अब स्पष्ट नहीं है।

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

इस प्रकार के spec के साथ fiddling आमतौर पर पर्याप्त है। यदि यह एक विशेष रूप से मुश्किल विशेषता है तो हम भारी उपकरण खींचते हैं। उदाहरण के लिए, जब LINQ को डिज़ाइन किया जाता है, तो कंपाइलर लोगों में से एक और आईडीई लोगों में से एक जो पार्सर सिद्धांत में पृष्ठभूमि रखते हैं, ने खुद को एक पार्सर जेनरेटर बनाया है जो अस्पष्टताओं की तलाश में व्याकरण का विश्लेषण कर सकता है, और उसके बाद क्वेरी समझ के लिए प्रस्तावित सी # व्याकरण खिलाया ; ऐसा करने से कई मामलों में पाया गया जहां प्रश्न अस्पष्ट थे।

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

आज सी # में अस्पष्टताएं हैं?

निश्चित रूप से।

G(F<A, B>(0)) 

सी # 1 में यह स्पष्ट है कि इसका क्या अर्थ है। यह वही है:

G((F<A), (B>0)) 

यही है, यह दो तर्कों के साथ जी को बुलाता है जो बूल हैं। सी # 2 में, इसका अर्थ यह हो सकता है कि इसका मतलब सी # 1 में क्या था, लेकिन इसका मतलब यह भी हो सकता है कि "जेनेरिक विधि एफ को पास करें 0 जो टाइप पैरामीटर ए और बी लेता है, और उसके बाद एफ से जी का परिणाम पास करता है"। हमने पार्सर को एक जटिल ह्युरिस्टिक जोड़ा जो निर्धारित करता है कि आपके द्वारा संभवतः दो मामलों में से कौन सा मामला है।

इसी तरह, डाले भी सी # 1.0 में अस्पष्ट हैं:

G((T)-x) 

है कि "टी करने के लिए -x डाली" या "टी से एक्स घटाना"? फिर, हमारे पास एक उदारवादी है जो एक अच्छा अनुमान लगाता है।

+0

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

+3

ओह क्षमा करें, मैं भूल गया ... बैट सिग्नल दृष्टिकोण, जबकि यह काम करता प्रतीत होता है, को (आईएमओ) संपर्क के प्रत्यक्ष माध्यमों को प्राथमिकता दी जाती है जिससे किसी को सार्वजनिक पोस्ट के लिए सार्वजनिक शिक्षा के लिए सार्वजनिक पोस्ट नहीं मिलती यह अनुक्रमणीय, खोजने योग्य, और आसानी से संदर्भित करने में सक्षम है। क्या हम एक मंचित एसओ पोस्ट/उत्तर नृत्य को कोरियोग्राफ करने के लिए सीधे संपर्क करेंगे? :) –

+5

मैं अनुशंसा करता हूं कि आप एक पोस्ट स्टेजिंग से बचें। यह उन लोगों के लिए उचित नहीं होगा जो इस प्रश्न में अतिरिक्त अंतर्दृष्टि प्राप्त कर सकते हैं। सवाल पोस्ट करने के लिए एक बेहतर तरीका होगा, फिर भागीदारी के लिए पूछे जाने वाले लिंक को ईमेल करें। – chilltemp

1

मैं कोई एरिक लिपर्ट नहीं हूं, इसलिए मैं निश्चित रूप से नहीं कह सकता हूं, लेकिन मुझे लगता है कि ऐसा इसलिए है क्योंकि प्रारंभिक निर्माण का अनुमान लगाने के लिए संकलक द्वारा खाली कोष्ठक की आवश्यकता नहीं है। इसलिए यह अनावश्यक जानकारी हो जाती है, और इसकी आवश्यकता नहीं होती है।

+0

ठीक है, यह अनावश्यक है, लेकिन मैं सिर्फ उत्सुक हूं कि अचानक उनका परिचय क्यों वैकल्पिक है? ऐसा लगता है कि भाषा वाक्यविन्यास स्थिरता के साथ तोड़ना है। अगर मेरे पास प्रारंभिक अवरोधक ब्लॉक को इंगित करने के लिए खुली घुंघराले ब्रेस नहीं है, तो यह अवैध वाक्यविन्यास होना चाहिए। मजेदार आप श्री लिपर्ट का जिक्र करते हैं, मैं अपने जवाब के लिए सार्वजनिक रूप से मछली पकड़ने का था ताकि स्वयं और दूसरों को निष्क्रिय जिज्ञासा से फायदा होगा। :) –

9

क्योंकि इस तरह भाषा को निर्दिष्ट किया गया था। वे कोई मूल्य नहीं जोड़ते हैं, तो उन्हें क्यों शामिल करें?

यह भी टाइप किया सरणियों

बहुत implicity के समान है
var a = new[] { 1, 10, 100, 1000 };   // int[] 
var b = new[] { 1, 1.5, 2, 2.5 };   // double[] 
var c = new[] { "hello", null, "world" };  // string[] 
var d = new[] { 1, "one", 2, "two" };   // Error 

संदर्भ: http://msdn.microsoft.com/en-us/library/ms364047%28VS.80%29.aspx

+1

वे इस अर्थ में कोई मूल्य नहीं जोड़ते कि यह स्पष्ट होना चाहिए कि इरादा क्या है, लेकिन यह स्थिरता के साथ टूट जाता है कि अब हमारे पास दो अलग-अलग ऑब्जेक्ट निर्माण वाक्यविन्यास हैं, एक कोष्ठक के साथ एक (और इसमें अल्पविराम-सीमित तर्क अभिव्यक्तियां) और बिना एक। –

+1

@ जेम्स ड्यून, यह वास्तव में टाइप किए गए सरणी वाक्यविन्यास के लिए वास्तव में बहुत ही समान वाक्यविन्यास है, मेरा संपादन देखें। कोई प्रकार नहीं, कोई कन्स्ट्रक्टर नहीं है, और इरादा स्पष्ट है, इसलिए इसे – CaffGeek

7

यह वस्तुओं के निर्माण को आसान बनाने के लिए किया गया था। भाषा डिजाइनरों (मेरी जानकारी के लिए) नहीं है विशेष रूप से कहा है कि वे महसूस किया कि यह उपयोगी था, हालांकि यह स्पष्ट रूप से C# Version 3.0 Specification page में बताया गया है: प्रदान की

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

मुझे लगता है कि वे कोष्ठक महसूस किया है, इस उदाहरण में, आदेश, डेवलपर के इरादे को दिखाने के लिए के बाद से ऑब्जेक्ट प्रारंभकर्ता आशय का निर्माण और बजाय वस्तु के गुणों को सेट करने से पता चलता में आवश्यक नहीं थे।

4

आपके पहले उदाहरण में, कंपाइलर अनुमान लगाता है कि आप डिफ़ॉल्ट कन्स्ट्रक्टर को कॉल कर रहे हैं (सी # 3.0 भाषा विशिष्टता बताती है कि यदि कोई कंस्ट्रैसिस प्रदान नहीं किया जाता है, तो डिफ़ॉल्ट कन्स्ट्रक्टर कहा जाता है)।

दूसरे में, आप स्पष्ट रूप से डिफ़ॉल्ट कन्स्ट्रक्टर को कॉल करते हैं।

आप रचनाकार को मूल्यों को स्पष्ट रूप से पास करते समय गुणों को सेट करने के लिए उस वाक्यविन्यास का भी उपयोग कर सकते हैं। आप निम्न वर्ग परिभाषा था:

public class SomeTest 
{ 
    public string Value { get; private set; } 
    public string AnotherValue { get; set; } 
    public string YetAnotherValue { get; set;} 

    public SomeTest() { } 

    public SomeTest(string value) 
    { 
     Value = value; 
    } 
} 

तीनों बयानों मान्य हैं:

var obj = new SomeTest { AnotherValue = "Hello", YetAnotherValue = "World" }; 
var obj = new SomeTest() { AnotherValue = "Hello", YetAnotherValue = "World"}; 
var obj = new SomeTest("Hello") { AnotherValue = "World", YetAnotherValue = "!"}; 
+0

दाएं घोषित करने की आवश्यकता नहीं है। आपके उदाहरण में पहले और दूसरे मामले में ये कार्यात्मक रूप से समान हैं, सही? –

+1

@ जेम्स ड्यून - सही। वह भाषा विशिष्टता द्वारा निर्दिष्ट हिस्सा है। खाली कोष्ठक अनावश्यक हैं, लेकिन आप अभी भी उन्हें आपूर्ति कर सकते हैं। –

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