क्यों बयान (j ++) था; मना किया हुआ?


169

निम्नलिखित कोड गलत है (इसे ideone पर देखें ):

public class Test
{
    public static void Main()
    {
        int j = 5;
        (j++);      // if we remove the "(" and ")" then this compiles fine.
    }
}

त्रुटि CS0201: केवल असाइनमेंट, कॉल, वेतन वृद्धि, वेतन वृद्धि, प्रतीक्षा, और नए ऑब्जेक्ट एक्सप्रेशन को एक कथन के रूप में उपयोग किया जा सकता है

  1. जब हम कोष्ठक हटाते हैं तो कोड क्यों संकलित करता है?
  2. यह कोष्ठक के साथ संकलन क्यों नहीं करता है?
  3. C # को क्यों बनाया गया था?

29
@ सेरी भाषा के डिज़ाइन से जुड़े बहुत से लोग SO पर हैं, इसलिए मैंने पूछा। इसमें कुछ भी गलत है?
user10607

34
मैं "क्यों एक विशिष्ट प्रोग्रामिंग भाषा इस विशिष्ट व्यवहार को इस तरह से संभालती है?" की तुलना में अधिक ऑन-टॉपिक प्रश्न की कल्पना नहीं कर सकती।
मग Xy

20
अब हमारे पास एरिक लिपर्ट का जवाब है। हो सकता है कि आप स्वीकृत उत्तर के बारे में अपने निर्णय पर फिर से विचार करना चाहते हों। यह क्रिसमस है, इसलिए शायद आपने जवाब बहुत जल्दी स्वीकार कर लिया है।
थॉमस वेलर

17
@ सरवाइव कर रहे हैं कि डिजाइन के निर्णय कभी प्रलेखित नहीं होते हैं और बाकी सभी के लिए बिल्कुल अज्ञात होते हैं? वह एसओ उपयोगकर्ताओं को अनुमान लगाने के लिए नहीं कह रहा है, वह जवाब मांग रहा है - इसका मतलब यह नहीं है कि वह अनुमान लगा रहा है। लोग एक अनुमान के साथ जवाब देने चाहे पर है उन्हें , उसे नहीं। और जैसा कि ओ पी ने कहा, वहाँ रहे हैं जो ढेर अतिप्रवाह पर लोगों से किया था वास्तव में पर सी # काम करते हैं और ये निर्णय लिए।
रोब

5
@ रब: समस्या यह है कि, हाँ, जब तक कि औचित्य पहले से ही कहीं दस्तावेज नहीं है, यह होना चाहिए, लेकिन अटकलें मजेदार हैं और कौन अपने स्वयं को साझा नहीं करना चाहता है? यदि आप इस तरह के शुद्ध (या "शिक्षित") अनुमानों को सुनिश्चित करने का एक तरीका ढूंढते हैं, तो अनुमान है कि यह विश्वसनीय है, मुझे बताएं और हम भाग्य बनाएंगे।
डेडुप्लिकेटर

जवाबों:


221

गहरी अंतर्दृष्टि की सराहना की।

मैं अपना सर्वश्रेष्ठ प्रदर्शन करूंगा।

जैसा कि अन्य उत्तरों ने उल्लेख किया है, यहां क्या चल रहा है संकलक यह पता लगा रहा है कि एक अभिव्यक्ति को एक बयान के रूप में इस्तेमाल किया जा रहा है । कई भाषाओं में - सी, जावास्क्रिप्ट और कई अन्य - एक बयान के रूप में अभिव्यक्ति का उपयोग करना पूरी तरह से कानूनी है। 2 + 2;इन भाषाओं में कानूनी है, भले ही यह एक बयान है जिसका कोई प्रभाव नहीं है। कुछ अभिव्यक्तियाँ केवल उनके मूल्यों के लिए उपयोगी होती हैं, कुछ अभिव्यक्तियाँ केवल उनके दुष्प्रभावों के लिए उपयोगी होती हैं (जैसे कि शून्य वापसी पद्धति के लिए कॉल) और कुछ भाव, दुर्भाग्य से, दोनों के लिए उपयोगी होते हैं। (वेतन वृद्धि की तरह)

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


ASIDE: एक आम तौर पर एक वस्तु निर्माण के बारे में सोचता है कि इसका उपयोग उस मूल्य के लिए किया जाता है, न कि निर्माण के दुष्प्रभाव के लिए; मेरी राय में अनुमति new Foo();देना एक मिसफिट सा है। विशेष रूप से, मैंने इस पैटर्न को वास्तविक-विश्व कोड में देखा है जिससे सुरक्षा दोष उत्पन्न हुआ:

catch(FooException ex) { new BarException(ex); } 

यदि कोड जटिल है, तो इस दोष को स्पॉट करना आश्चर्यजनक रूप से कठिन हो सकता है।


इसलिए कंपाइलर उन सभी कथनों का पता लगाने के लिए काम करता है, जो उस सूची में शामिल नहीं हैं। विशेष रूप से, कोष्ठक अभिव्यक्तियों की पहचान बस के रूप में की जाती है - कोष्ठक अभिव्यक्तियाँ। वे "बयान अभिव्यक्तियों के रूप में अनुमत" की सूची में नहीं हैं, इसलिए वे अस्वीकृत हैं।

यह सब C # भाषा के एक डिजाइन सिद्धांत की सेवा में है। यदि आप टाइप (x++);करते हैं तो आप शायद कुछ गलत कर रहे थे । यह शायद M(x++);या कुछ और बात के लिए एक टाइपो है। याद रखें, सी # संकलक टीम का रवैया नहीं है " हम किसी तरह से इस काम करने के लिए यह पता लगाने कर सकते हैं? " सी # संकलक टीम का रवैया है " का अगर एक संभावना गलती की तरह प्रशंसनीय कोड दिखता है, चलो डेवलपर को सूचित "। C # डेवलपर्स को वह रवैया पसंद है।

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

क्या रिटर्न myVar बनाम रिटर्न (myVar) के बीच अंतर है?


5
पुन: "एक सामान्य रूप से एक निर्माता के आह्वान के बारे में सोचता है कि इसका उपयोग उस मूल्य के लिए किया जा रहा है, न कि निर्माण के दुष्प्रभाव के लिए, मेरी राय में यह एक मिसफिट का एक सा है": मैं कल्पना करूँगा कि इस निर्णय में एक कारक यह था कि अगर संकलक ने इसे मना किया, तो उन मामलों में कोई साफ-सुथरा फिक्स नहीं होगा, जहां आप इसे साइड-इफेक्ट के लिए बुला रहे हैं । (अधिकांश अन्य निषिद्ध अभिव्यक्ति के बयानों में बाहरी हिस्से होते हैं जो बिना किसी उद्देश्य के काम करते हैं और इन्हें हटाया जा सकता है, इसके अपवाद के साथ ... ? ... : ..., जहां फिक्स का उपयोग if/ elseइसके बजाय करना है।)
23

1
@ruakh: चूंकि यह ऐसा व्यवहार है जिसे हतोत्साहित किया जाना चाहिए, इसलिए एक साफ फिक्स आवश्यक नहीं है, इसलिए जब तक कि एक यथोचित सस्ता / सरल फिक्स न हो। जो वहां है; इसे किसी वैरिएबल को असाइन करें और उस वैरिएबल का उपयोग न करें। यदि आप स्पष्ट होना चाहते हैं कि आप इसका उपयोग नहीं कर रहे हैं, तो कोड की उस पंक्ति को स्वयं का दायरा दें। जबकि तकनीकी रूप से कोई यह तर्क दे सकता है कि यह कोड के शब्दार्थ (एक बेकार संदर्भ असाइनमेंट अभी भी एक बेकार संदर्भ असाइनमेंट) है, व्यवहार में यह बात होने की संभावना नहीं है। मैं मानता हूं कि यह थोड़ा अलग आईएल उत्पन्न करता है ... लेकिन केवल अगर अनुकूलन के बिना संकलित किया गया हो।
ब्रायन

सफारी, फ़ायरफ़ॉक्स, और क्रोम सभी टाइपिंग करते समय ReferenceError देते हैं contineu;
ब्रायन मैककिनटन

2
@McBrainy: आप सही कह रहे हैं। मैं उस गलतफहमी को दूर कर रहा हूं जो गलत वर्तनी से उत्पन्न होता है; मैं अपने नोट्स की जांच करूंगा। इस बीच मैं अपमानजनक बयान को हटा दिया है क्योंकि यह यहाँ बड़े बिंदु पर नहीं है।
एरिक लिपर्ट

1
@ माइक: मैं सहमत हूं। एक और स्थिति जिसमें हम कभी-कभी बयान देखते हैं जैसे कि परीक्षण के मामले हैं, try { new Foo(null); } catch (ArgumentNullException)...लेकिन जाहिर है कि ये परिस्थितियां उत्पादन कोड नहीं हैं। यह उचित लगता है कि डमी वैरिएबल को असाइन करने के लिए ऐसा कोड लिखा जा सकता है।
एरिक लिपर्ट

46

में सी # भाषा विनिर्देश

अभिव्यक्ति के बयान अभिव्यक्ति का मूल्यांकन करने के लिए उपयोग किए जाते हैं। अभिव्यक्तियों को बयान के रूप में उपयोग किया जा सकता है, नए ऑपरेटर का उपयोग करते हुए विधि इनवोकेशन, ऑब्जेक्ट आवंटन शामिल हैं = और कंपाउंड असाइनमेंट ऑपरेटरों का उपयोग करते हुए ++ और - ऑपरेटर्स का उपयोग करके वेतन वृद्धि और वेतन वृद्धि संचालन और अभिव्यक्ति का इंतजार करते हैं।

एक विवरण के चारों ओर कोष्ठक लगाने से एक नया तथाकथित कोष्ठक अभिव्यक्ति बनती है। विनिर्देशन से:

एक कोष्ठक-अभिव्यक्ति में कोष्ठकों में संलग्न अभिव्यक्ति होती है। ... एक कोष्ठक-अभिव्यक्ति का मूल्यांकन कोष्ठकों के भीतर अभिव्यक्ति का मूल्यांकन करके किया जाता है। यदि कोष्ठकों के भीतर की अभिव्यक्ति नामस्थान या प्रकार को दर्शाती है, तो संकलन-समय त्रुटि उत्पन्न होती है। अन्यथा, कोष्ठक-अभिव्यक्ति का परिणाम निहित अभिव्यक्ति के मूल्यांकन का परिणाम है।

चूंकि कोष्ठक अभिव्यक्तियाँ एक मान्य अभिव्यक्ति कथन के रूप में सूचीबद्ध नहीं हैं, इसलिए यह विनिर्देश के अनुसार एक मान्य कथन नहीं है। डिजाइनरों ने इसे ऐसा करने के लिए क्यों चुना इस तरह से किसी का अनुमान है, लेकिन मेरी शर्त यह है क्योंकि यदि पूरे विवरण कोष्ठक में समाहित है, तो कोष्ठक कोई उपयोगी काम नहीं करते हैं : stmtऔर (stmt)बिल्कुल समान हैं।


4
@ सरवी: यदि आप बारीकी से पढ़ते हैं, तो यह उससे थोड़ा अधिक बारीक था। तथाकथित "एक्सप्रेशन स्टेटमेंट" वास्तव में एक मान्य स्टेटमेंट है, और विनिर्देश उन अभिव्यक्तियों के प्रकारों को सूचीबद्ध करता है जो मान्य कथन हो सकते हैं। हालाँकि, मैं इस अनुमान से दोहराता हूं कि "पैरेंटाइज़्ड एक्सप्रेशन" नामक अभिव्यक्ति का प्रकार वैध अभिव्यक्तियों की सूची में नहीं है, जिसे वैध अभिव्यक्ति स्टेटमेंट के रूप में इस्तेमाल किया जा सकता है।
फ्रैंक ब्राइस

4
OPभाषा डिजाइन के बारे में कुछ भी नहीं पूछ रहा है। वह सिर्फ यह जानना चाहता है कि यह एक त्रुटि क्यों है। उत्तर है: क्योंकि यह एक मान्य कथन नहीं है
लिएंड्रो

9
ठीक है, मेरा बुरा। इसका उत्तर है: क्योंकि, विनिर्देश के अनुसार , यह एक मान्य कथन नहीं है। वहाँ आपके पास है: एक डिजाइन कारण!
लिएंड्रो

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

4
@Servy JohnCarpenter केवल यह नहीं कह रही है कि "आप ऐसा नहीं कर सकते।" वह कह रहा है, जिन दो चीजों से आप भ्रमित थे, वे एक जैसी नहीं हैं। j ++ एक अभिव्यक्ति कथन है, जबकि (j ++) एक कोष्ठक-अभिव्यक्ति है। अचानक ओपी को अब फर्क पता चल गया है कि वे क्या हैं। यह एक अच्छा जवाब है। यह शीर्षक नहीं उसके सवाल का शरीर जवाब देता है। मुझे लगता है कि सवाल के शीर्षक में "डिज़ाइन" शब्द से बहुत सारे विवाद आते हैं, लेकिन इसका जवाब डिजाइनरों द्वारा नहीं दिया जाना चाहिए, बस विनिर्देशों से चमकता हुआ।
विचार

19

के आसपास कोष्ठक i++को एक अभिव्यक्ति बना रहे हैं / परिभाषित कर रहे हैं .. जैसा कि त्रुटि संदेश कहता है .. कथन के रूप में एक सरल अभिव्यक्ति का उपयोग किया जा सकता है।

भाषा इस तरह से क्यों बनाई गई थी? बग को रोकने के लिए, बयानों के रूप में भ्रामक अभिव्यक्ति होने से, कोड होने जैसा कोई दुष्प्रभाव नहीं होता है

int j = 5;
j+1; 

दूसरी पंक्ति का कोई प्रभाव नहीं है (लेकिन आपने ध्यान नहीं दिया होगा)। लेकिन संकलक के बजाय इसे हटाने (क्योंकि कोड की आवश्यकता नहीं है)। यह स्पष्ट रूप से आपको इसे हटाने के लिए कहता है (ताकि आप अवगत या त्रुटि होंगे) या इसे ठीक करें यदि आप कुछ टाइप करना भूल गए हैं।

संपादित करें :

कोष्ठक के बारे में अधिक स्पष्ट बनाने के लिए .. c # में कोष्ठक (अन्य उपयोगों जैसे, कास्ट और फ़ंक्शन कॉल के अलावा), समूह अभिव्यक्तियों के लिए उपयोग किए जाते हैं, और एकल अभिव्यक्ति (उप अभिव्यक्तियों का निर्माण) लौटाते हैं।

कोड के उस स्तर पर केवल हकलाने की अनुमति है .. इसलिए

j++; is a valid statement because it produces side effects

लेकिन ब्रैड का उपयोग करके आप इसे अभिव्यक्ति के रूप में बदल रहे हैं

myTempExpression = (j++)

और इस

myTempExpression;

संकलक मान्य नहीं होने के कारण यह मान्य नहीं है कि साइड इफेक्ट के रूप में अभिव्यक्ति। (हॉल्टिंग समस्या में आए बिना नहीं) ।।


हाँ, यही मैंने पहले भी सोचा था। लेकिन इस करता है एक पक्ष प्रभाव है। यह jचर के बाद के वेतन वृद्धि का प्रदर्शन करता है ?
user10607

1
j++;एक मान्य कथन है, लेकिन आपके द्वारा कहे जा रहे कोष्ठक का उपयोग करके let me take this stement and turn it into an expression.. और
एक्सप्रेशन

यह बहुत बुरा है कि "गणना और अनदेखी" बयान का कोई रूप नहीं है, क्योंकि ऐसे अवसर होते हैं जब कोड यह दावा कर सकता है कि एक अपवाद को फेंकने के बिना एक मूल्य की गणना की जा सकती है, लेकिन इस प्रकार गणना किए गए वास्तविक मूल्य के बारे में परवाह नहीं है। एक कम्प्यूट-एंड-इग्निशन स्टेटमेंट का अक्सर उपयोग नहीं किया जाएगा, लेकिन ऐसे मामलों में प्रोग्रामर का इरादा स्पष्ट कर देगा।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.