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;
पार्स करके कानूनी है अगर x
int*
है।)
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 डाली" या "टी से एक्स घटाना"? फिर, हमारे पास एक उदारवादी है जो एक अच्छा अनुमान लगाता है।
एक तरफ के रूप में, हमने इसे पिछले सप्ताह एक कोड समीक्षा में पाया: var list = new list {}; अगर कुछ दुर्व्यवहार किया जा सकता है ... –
blu
@blu यही कारण है कि मैं इस सवाल से पूछना चाहता था। मैंने हमारे कोड में असंगतता देखी। सामान्य रूप से असंगतता मुझे परेशान करती है इसलिए मैंने सोचा कि मैं देखता हूं कि वाक्यविन्यास में वैकल्पिकता के पीछे कोई अच्छा तर्क था या नहीं। :) –
संभावित डुप्लिकेट [ऑब्जेक्ट प्रारंभकर्ता और कन्स्ट्रक्टर के बीच क्या अंतर है?] (Http://stackoverflow.com/questions/740658/whats-the-difference-between-an-object-initializer-and-a- कन्स्ट्रक्टर) –