C # आसानी से स्थानीय चर क्यों नहीं हटाता है?


115

इस बारे में एक सहकर्मी के साथ मैत्रीपूर्ण बहस होना। इस बारे में हमारे कुछ विचार हैं, लेकिन आश्चर्य है कि एसओ भीड़ इस बारे में क्या सोचती है?


4
@ColonelPanic C और C ++ में कॉन्स्टेबल लोकल वैरिएबल हैं, जिन्हें आप रनटाइम-कंप्यूटेड वैल्यू के साथ इनिशियलाइज़ कर सकते हैं।
रात्रि

1
जावास्क्रिप्ट 2015 (ES6) में कांस्ट प्रकार है। जैसे {const myList = [1,2,3]; }। इस निर्माण का उपयोग करने के लिए यह बहुत अच्छा प्रोग्रामिंग अभ्यास है। अधिक जानकारी: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
andrew.fox

1
रुचि रखने वालों के लिए, इस सुविधा के लिए एक UserVoice सुझाव है । यह वर्तमान में केवल 87 वोट पर बैठा है, इसलिए यदि आप स्थानीय आसानी से चर देखना चाहते हैं, तो कृपया इसे टक्कर दें!
इयान केम्प

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

1
अपडेट 2017 : कृपया सी # भाषा डिज़ाइन रेपो में चर्चा के तहत सुविधा अनुरोध के लिए वोट करें! github.com/dotnet/csharplang/issues/188
कर्नल पैनिक

जवाबों:


15

एक कारण यह है कि एक स्थानीय के लिए सीएलआर समर्थन नहीं है। Readonly का अनुवाद CLR / CLI initonly opcode में होता है। यह ध्वज केवल खेतों में लगाया जा सकता है और इसका स्थानीय के लिए कोई अर्थ नहीं है। वास्तव में, इसे स्थानीय में लागू करने की संभावना अपरिवर्तनीय कोड का उत्पादन करेगी।

इसका मतलब यह नहीं है कि C # ऐसा नहीं कर सका। लेकिन यह एक ही भाषा के निर्माण के लिए दो अलग-अलग अर्थ देगा। स्थानीय लोगों के लिए संस्करण में कोई सीएलआर समकक्ष मैपिंग नहीं होगी।


57
यह वास्तव में सुविधा के लिए सीएलआई समर्थन के साथ कुछ नहीं करना है, क्योंकि स्थानीय चर किसी भी तरह से अन्य विधानसभाओं के संपर्क में नहीं हैं। readonlyक्षेत्रों के लिए कीवर्ड CLI द्वारा समर्थित होने की वजह से उसके प्रभाव की जरूरत है अन्य विधानसभाओं के लिए दिखाई दे। इसका मतलब यह होगा कि कंपाइलिंग टाइम में केवल एक ही वेरिएबल है।
सैम हैरवेल

16
मुझे लगता है कि आपने सिर्फ इस सवाल को स्थानांतरित किया है कि सीएलआर इसके पीछे तर्कसंगत प्रदान करने के बजाय इसका समर्थन क्यों नहीं करता है। यह कास्ट स्थानीय लोगों के लिए अनुमति देता है, इसलिए यह उचित होगा कि स्थानीय लोगों को भी उम्मीद की जाए।
चाड शाउगिन्स

9
इसका एक उदाहरण एक प्रयोग कथन में परिवर्तनीय है। वे स्थानीय हैं ... और आसानी से (उन्हें असाइन करने का प्रयास करें, सी # एक त्रुटि जोड़ देगा)।
सॉफ्टलियन

7
-1 C + में कोई मशीन कोड सपोर्ट नहीं है const(जो C ++ में C # readonlyकी तरह C # की तरह अधिक है const, हालांकि यह दोनों भूमिका निभा सकता है)। फिर भी C ++ constस्थानीय स्वचालित चर के लिए समर्थन करता है । इसलिए readonlyस्थानीय चर के लिए C # के लिए CLR समर्थन की कमी , अप्रासंगिक है।
चीयर्स एंड हीथ। - अल्फ

5
1. यह आसानी से एक संकलक सुविधा हो सकती है, जैसे C ++ में। सीएलआर सपोर्ट पूरी तरह अप्रासंगिक है। मशीन असेंबली इसका समर्थन नहीं करती है, तो क्या? 2. (यह) संभावना अपरिवर्तनीय कोड का उत्पादन करेगा - मैं नहीं देखता कि कैसे, लेकिन शायद मैं गलत हूं। 3. यह एक ही भाषा के निर्माण के लिए दो अलग-अलग अर्थ देगा - मुझे संदेह है कि कोई भी इसे एक मुद्दे के रूप में देखेगा, क्योंकि usingऔर outठीक यही कर रहे हैं और दुनिया का पतन नहीं हुआ है।
लो

66

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


11
मैं "प्रोग्रामर को स्वयं से बचाने" वाले भाग पर सहमत हूं, लेकिन कोड को ऑप्टिमाइज़ करने में कंपाइलर की मदद करने के लिए, मैं इस बात को रखता हूं कि कंपाइलर यह अच्छी तरह से पता लगा सकता है कि विधि के दौरान कोई परिवर्तनशील परिवर्तन है या नहीं और तदनुसार अनुकूलन करता है या नहीं। किसी भी तरह से। ऑप्टिमाइज़र को इस उद्देश्य के लिए वैसे भी पहचानने से पहले कि कुछ भी वास्तव में लाभ नहीं देता है, 'रीडोनली' फ्लैग रखने से वास्तव में फायदा नहीं होता है।
कॉर्नेलियस

1
@ कॉर्नेलियस मैं मानता हूं कि ऐसी राय है कि कुछ मामलों में कंपाइलर किसी भी कीवर्ड / मोडिफ़ायर की परवाह किए बिना ऑप्टिमाइज़ेशन के अवसर का पता लगाने के लिए डेटा-फ़्लो डायग्राम का उपयोग करता है। लेकिन प्रोग्रामर को अपने आप को गलत लिखने से बचाना और अन्यथा अनावश्यक रूप से अनधिकृत कोड संकलक के लिए उस अनुकूलन अवसर को खोल सकता है।
शुवा

आधुनिक संकलक वैसे भी स्टैटिक सिंगल असाइनमेंट नहीं करते हैं? इस मामले में जहां तक ​​अनुकूलन की बात है तो यह बहुत ही कम है (लेकिन यदि कोई कंपाइलर SSA को सपोर्ट करता है तो इसका मतलब है कि यह असाइनमेंट को एक बार लागू करने के लिए मामूली है)।
दाई

33

जेरेड के जवाब को संबोधित करते हुए, यह शायद केवल एक संकलन-समय की विशेषता होगी - संकलक आपको प्रारंभिक घोषणा के बाद चर को लिखने से रोक देगा (जिसमें एक असाइनमेंट शामिल करना होगा)।

क्या मैं इसमें मूल्य देख सकता हूं? संभावित रूप से - लेकिन बहुत कुछ नहीं, ईमानदार होने के लिए। यदि आप आसानी से यह नहीं बता सकते हैं कि कोई चर विधि में कहीं और सौंपा जा रहा है या नहीं, तो आपकी विधि बहुत लंबी है।

क्या यह की कीमत के लिए, जावा इस सुविधा (का उपयोग करते हुए है finalसंशोधक) और मैं गए हैं बहुत मुश्किल से ही देखा यह उन मामलों में जहां यह के अलावा अन्य के लिए इस्तेमाल किया है चर एक गुमनाम आंतरिक वर्ग द्वारा कब्जा कर लिया जा करने के लिए अनुमति देने के लिए प्रयोग की जाने वाली है - और जहां यह है उपयोग किया जाता है, यह मुझे उपयोगी जानकारी के बजाय अव्यवस्था का आभास देता है।


75
यह देखने में अंतर है कि क्या चर आपकी दृष्टि में और संकलक द्वारा संशोधित किया गया है या नहीं । मुझे एक विधि लिखने में कोई आपत्ति नहीं है, एक चर को संशोधित नहीं करने के लिए मेरा इरादा बताते हुए, और संकलक ने मुझे सूचित किया जब मैं गलती से करता हूं (शायद एक महीने बाद टाइपो के साथ)!
ए रेक्स

50
दूसरी ओर, F # में सभी चर केवल डिफ़ॉल्ट रूप से पढ़े जाते हैं, और यदि आप उन्हें बदलने में सक्षम होना चाहते हैं तो आपको 'परिवर्तनशील' कीवर्ड का उपयोग करना होगा। चूँकि F # एक .NET लैंग्वेज है, मुझे लगता है कि यह आपके द्वारा वर्णित संकलन-समय की जाँच करता है।
जोएल मुलर

2
@ A.Rex: यह सवाल वास्तव में है कि क्या उस चेक को करने के लिए कंपाइलर का लाभ कोड को पढ़ते समय अतिरिक्त "फ़्लफ़" के लायक है और वास्तव में इसकी परवाह नहीं है।
जॉन स्कीट

3
FWIW, Scala स्थानीय readonly/ finalमानों को चर valऔर varकीवर्ड से अलग करता है। स्काला कोड में, लोकल valएस का बहुत बार उपयोग किया जाता है (और, वास्तव में, स्थानीय varएस पर पसंद किया जाता है )। मुझे संदेह है कि finalजावा में संशोधक का अधिक बार उपयोग नहीं किए जाने के प्राथमिक कारण क) अव्यवस्था और ख) आलस्य हैं।
आरोन नोवस्त्रुप

4
स्थानीय वैरिएबल के लिए जिनका उपयोग क्लोजर में नहीं किया जाता है, readonlyअत्यधिक महत्वपूर्ण नहीं होंगे। दूसरी ओर, स्थानीय चर जो क्लोजर में उपयोग किए जाते हैं, readonlyकई मामलों में संकलक को अधिक कुशल कोड उत्पन्न करने देगा। वर्तमान में, जब निष्पादन एक ब्लॉक में प्रवेश करता है जिसमें एक क्लोजर होता है, तो कंपाइलर को क्लोज-ओवर वेरिएबल्स के लिए एक नया हीप ऑब्जेक्ट बनाना होगा, भले ही कोई कोड जो क्लोजर का उपयोग करेगा कभी निष्पादित नहीं होता है । यदि एक चर केवल-पढ़ने के लिए था, तो बंद के बाहर कोड एक सामान्य चर का उपयोग कर सकता है; केवल जब एक प्रतिनिधि को बंद करने के लिए बनाया जाता है ...
21

30

C # 7 डिज़ाइन टीम द्वारा एक प्रस्ताव को स्थानीय लोगों और मापदंडों के लिए संक्षेप में चर्चा की गई थी। से जनवरी 21, 2015 के लिए सी # डिजाइन बैठक नोट्स :

पैरामीटर और स्थानीय लोगों को लैम्ब्डा द्वारा कैप्चर किया जा सकता है और इस तरह समवर्ती रूप से एक्सेस किया जा सकता है, लेकिन साझा-पारस्परिक-राज्य के मुद्दों से उन्हें बचाने का कोई तरीका नहीं है: उन्हें आसानी से पढ़ा नहीं जा सकता है।

सामान्य तौर पर, अधिकांश मापदंडों और कई स्थानीय लोगों को उनके प्रारंभिक मूल्य प्राप्त करने के बाद कभी भी सौंपा जाने का इरादा नहीं होता है। उन पर आसानी से अनुमति देने से वह इरादा स्पष्ट रूप से प्रकट होगा।

एक समस्या यह है कि यह सुविधा एक "आकर्षक उपद्रव" हो सकती है। जबकि "सही बात" करने के लिए लगभग हमेशा पैरामीटर और स्थानीय लोगों को आसानी से बनाना होगा, यह ऐसा करने के लिए कोड को काफी अव्यवस्थित करेगा।

आंशिक रूप से इसे कम करने का एक विचार यह है कि किसी स्थानीय चर पर संयोजन को आसानी से वैली या उससे कुछ छोटा करार दिया जाए। आम तौर पर हम केवल एक छोटे कीवर्ड के बारे में सोचने की कोशिश कर सकते हैं, जो कि रीडोनली-नेस को व्यक्त करने के लिए आसानी से स्थापित हो।

C # भाषा डिज़ाइन रेपो में चर्चा जारी है। अपना समर्थन दिखाने के लिए वोट करें। https://github.com/dotnet/csharplang/issues/188


आसानी से डिफ़ॉल्ट (कुछ विकल्प या कीवर्ड या जो भी हो) कर सकता है। अधिकांश चर और मापदंडों को केवल कुछ लिखने योग्य होने के साथ, आसानी से पढ़ा जाना चाहिए। और संख्या को कम करना जो कि योग्य हैं आमतौर पर एक अच्छी बात है।
डेव कजिनो

12

यह c # भाषा डिजाइनर के लिए एक निरीक्षण है। F # में वैल कीवर्ड है और यह CLR पर आधारित है। कोई कारण नहीं है C # में समान भाषा विशेषता नहीं हो सकती।


7

मैं वह सहकर्मी था और यह अनुकूल नहीं था! (मजाक कर रहा हूं)

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

व्यक्तिगत रूप से, मैं अव्यवस्था से बचने के लिए एक और "var" प्रकार का कीवर्ड चाहता था जैसे "inv" (अपरिवर्तनीय) या "rvar"। मैं देर से के रूप में एफ # का अध्ययन कर रहा हूं और अपील करने वाली अपरिवर्तनीय बात का पता लगाता हूं।

कभी नहीं पता था कि जावा के पास यह है।


5

मैं स्थानीय री- वेरिएबल को उसी तरह से पसंद करूंगा, जैसे मुझे स्थानीय कॉन्स्टेबल वेरिएबल पसंद हैं । लेकिन अन्य विषयों की तुलना में इसकी प्राथमिकता कम है।
हो सकता है कि इसकी प्राथमिकता C # डिजाइनरों के लिए इस सुविधा को लागू न करने (अभी तक!) के लिए एक ही कारण हो । लेकिन भविष्य के संस्करणों में स्थानीय पठनीय चर का समर्थन करना आसान (और पीछे संगत) होना चाहिए।


2

केवल पढ़ने का मतलब है कि एक ही स्थान उदाहरण सेट किया जा सकता है जो कंस्ट्रक्टर में है। स्थानीय रूप से एक चर घोषित करते समय इसका कोई उदाहरण नहीं है (यह सिर्फ दायरे में है), और इसे कंस्ट्रक्टर द्वारा छुआ नहीं जा सकता है।


6
यह C # में 'आसानी से' का वर्तमान अर्थ है, लेकिन यह सवाल नहीं है। English रीड ओनली ’का एक अंग्रेजी अर्थ है जो लगता है कि एक स्थानीय चर के लिए सहज ज्ञान युक्त अनुप्रयोग है: आप इसे लिख नहीं सकते हैं (इसे शुरू करने के बाद)। उदाहरण के लिए वैरिएबल पर लागू होने पर यह बहुत पसंद आता है, इसलिए (जैसा कि औचित्य, मुझे लगता है) क्या हम इसे स्थानीय चरों पर लागू नहीं कर सकते हैं?
स्पाइक 0xff

0

मुझे पता है, यह आपके प्रश्न का उत्तर क्यों नहीं देता है। फिर भी, इस प्रश्न को पढ़ने वाले लोग नीचे दिए गए कोड की सराहना कर सकते हैं।

यदि आप वास्तव में एक स्थानीय चर को ओवरराइड करते समय पैर में अपने आप को गोली मारने से चिंतित हैं, जिसे केवल एक बार सेट किया जाना चाहिए, और आप इसे अधिक विश्व स्तर पर सुलभ चर नहीं बनाना चाहते हैं, तो आप ऐसा कुछ कर सकते हैं।

    public class ReadOnly<T>
    {
        public T Value { get; private set; }

        public ReadOnly(T pValue)
        {
            Value = pValue;
        }

        public static bool operator ==(ReadOnly<T> pReadOnlyT, T pT)
        {
            if (object.ReferenceEquals(pReadOnlyT, null))
            {
                return object.ReferenceEquals(pT, null);
            }
            return (pReadOnlyT.Value.Equals(pT));
        }

        public static bool operator !=(ReadOnly<T> pReadOnlyT, T pT)
        {
            return !(pReadOnlyT == pT);
        }
    }

उदाहरण उपयोग:

        var rInt = new ReadOnly<int>(5);
        if (rInt == 5)
        {
            //Int is 5 indeed
        }
        var copyValueOfInt = rInt.Value;
        //rInt.Value = 6; //Doesn't compile, setter is private

शायद कम कोड के रूप में नहीं, rvar rInt = 5लेकिन यह काम करता है।


यहाँ मदद नहीं करता है। चर 'var' के साथ यह मुद्दा है: {var पाँच = 5 पाँच = 6; Assert.That (पाँच == 5)}
मरे

0

यदि आप C # इंटरैक्टिव कंपाइलर का उपयोग कर रहे हैं, तो आप C # में आसानी से स्थानीय चर घोषित कर सकते हैं csi:

>"C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe"
Microsoft (R) Visual C# Interactive Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.

Type "#help" for more information.
> readonly var message = "hello";
> message = "goodbye";
(1,1): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)

आप .csxस्क्रिप्ट प्रारूप में आसानी से स्थानीय चर भी घोषित कर सकते हैं ।


5
त्रुटि संदेश के अनुसार, messageयहां एक चर नहीं है, यह एक क्षेत्र के लिए संकलित है। यह नाइटपैकिंग नहीं है क्योंकि अंतर स्पष्ट रूप से इंटरेक्टिव C # के रूप में मौजूद है: int x; Console.WriteLine(x)कानूनी इंटरेक्टिव C # है (क्योंकि xयह एक फ़ील्ड है और अंतर्निहित रूप से आरंभिक है) void foo() { int x; Console.WriteLine(x); }(क्योंकि xयह एक चर है और इसे असाइन किए जाने से पहले उपयोग किया जाता है)। इसके अलावा, Expression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberTypeयह बताएगा कि xवास्तव में एक क्षेत्र है और एक स्थानीय चर नहीं है।
जेरोइन मोस्टर्ट जुएल

0

सी # पहले से ही एक पठनीय संस्करण है, हालांकि कुछ अलग वाक्यविन्यास में:

निम्नलिखित पंक्तियों पर विचार करें:

var mutable = myImmutableCalculationMethod();
readonly var immutable = mutable; // not allowed in C# 8 and prior versions
return immutable;

तुलना करना:

var mutable = myImmutableCalculationMethod();
string immutable() => mutable; // allowed in C# 7
return immutable();

बेशक, पहला समाधान संभवतः लिखने के लिए कम कोड हो सकता है। लेकिन दूसरा स्निपेट चर को संदर्भित करते समय आसानी से स्पष्ट कर देगा।


यह "केवल पढ़ने के लिए" नहीं है। यह एक लोकल फंक्शन है जो कैप्चर किए गए वैरिएबल को लौटाता है .. इसलिए बहुत सारे बेवजह ओवरहेड और बदसूरत सिंटैक्स, जो कोड-एक्सेस के दृष्टिकोण से अंतर्निहित वेरिएबल को केवल पढ़ने के लिए भी नहीं बनाता है। इसके अलावा, "म्यूटेबल" आमतौर पर वस्तुओं पर लागू होता है, स्थानीय चर पर नहीं .. विचार करें readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");:।
user2864740

-2

constकेवल चर को पढ़ने के लिए कीवर्ड का उपयोग करें ।

संदर्भ: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const

public class SealedTest
{
    static void Main()
    {
        const int c = 707;
        Console.WriteLine("My local constant = {0}", c);
    }
}

1
हम जावास्क्रिप्ट-शैली में रुचि रखते हैं, constजहां चर को इसके आरंभ के दौरान असाइन किया जा सकता है - न कि सीएसएआरपी-शैली constजहां केवल संकलन-समय के भाव का उपयोग किया जा सकता है। जैसे, आप नहीं कर सकते, const object c = new object();लेकिन एक readonlyस्थानीय आपको ऐसा करने की अनुमति देगा।
बिंकी डेसी

-5

मुझे लगता है कि ऐसा इसलिए है क्योंकि एक ऐसा फंक्शन जिसमें एक वेरिएबल वैरिएबल को कभी भी कॉल नहीं किया जा सकता है, और संभवत: इसके बारे में कुछ है जो इसके दायरे से बाहर है, और आपको कब आवश्यकता होगी?

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.