c# - Microsoft पठनीय मानों के साथ आसानी से फ़ील्ड की सलाह क्यों देता है?




immutability (5)

कक्षा पुस्तकालयों के विकास के लिए डिज़ाइन दिशानिर्देशों में , Microsoft कहता है:

केवल पढ़ने योग्य क्षेत्रों के लिए परिवर्तनशील प्रकार के उदाहरण निर्दिष्ट न करें।

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

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

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

तो, सबसे पहले और सबसे महत्वपूर्ण बात यह है कि , Microsoft ने उत्परिवर्तित प्रकारों के संदर्भ में आसानी से उपयोग करने की सलाह क्यों दी? मैं भी जानना चाहूंगा:

  • क्या आप अपने सभी कोड में इस डिज़ाइन गाइडलाइन का पालन करते हैं?
  • जब आप "readonly" कोड के एक टुकड़े में देखते हैं तो आप क्या उम्मीद करते हैं?

readonly क्षेत्रों के लिए readonly प्रकार के उदाहरणों को असाइन करें।

मुझे फ्रेमवर्क डिज़ाइन गाइडलाइन्स बुक (पृष्ठ १६१-१६२) में एक त्वरित नज़र आया था, और यह मूल रूप से बताता है कि आपने पहले से ही क्या देखा है। जो डफी की एक अतिरिक्त टिप्पणी है जो गाइडलाइन के बारे में बताती है-डी'ट्रे:

यह दिशानिर्देश आपको किससे बचाने की कोशिश कर रहा है, यह विश्वास है कि आपने एक गहरी अपरिवर्तनीय वस्तु ग्राफ का खुलासा किया है जब वास्तव में यह उथला है, और फिर ऐसा कोड लिखना जो मान लेता है कि पूरा ग्राफ़ अपरिवर्तनीय है।
- जो डफी

मुझे व्यक्तिगत रूप से लगता है कि कीवर्ड को आसानी से नाम दिया गया था। यह तथ्य कि यह केवल संदर्भ के कॉन्स्ट-नेस को निर्दिष्ट करता है, और संदर्भित ऑब्जेक्ट के कॉन्स्ट-नेस को नहीं, आसानी से भ्रामक स्थिति पैदा करता है।

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

इस दुर्भाग्यपूर्ण स्थिति को मापने के लिए, दिशानिर्देश बनाया गया था। जबकि मुझे लगता है कि इसकी सलाह मानवीय दृष्टिकोण से ध्वनि है (यह हमेशा स्पष्ट नहीं है कि कौन से प्रकार परस्पर हैं और जो अपनी परिभाषा को देखे बिना नहीं हैं, और यह शब्द गहरी अपरिवर्तनीयता का सुझाव देता है), मैं कभी-कभी कामना करता हूं, जब यह आता है कांस्ट-नेस घोषित करने के लिए, C # C ++ द्वारा प्रस्तावित एक समान स्वतंत्रता प्रदान करेगा, जहां आप पॉइंटर को पॉइंटर पर, या पॉइंट-टू-ऑब्जेक्ट पर, या दोनों पर या कुछ भी नहीं परिभाषित कर सकते हैं।


Microsoft के पास कुछ ऐसी अजीबोगरीब सलाह हैं। दूसरा जो तुरंत मन में आता है वह सार्वजनिक सदस्यों में सामान्य प्रकार के घोंसले के लिए नहीं है, जैसे List<List<int>> । मैं इन निर्माणों से बचने की कोशिश करता हूं जहां आसानी से संभव है, लेकिन जब मुझे यह उचित लगता है तो नौसिखिया-अनुकूल सलाह की उपेक्षा करें।

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


आप जिस वाक्य-विन्यास की तलाश कर रहे हैं, वह C ++ / CLI भाषा द्वारा समर्थित है:

const Example^ const obj;

पहले कास्ट संदर्भित ऑब्जेक्ट को अपरिवर्तनीय बनाता है, दूसरा संदर्भ को अपरिवर्तनीय बनाता है। बाद वाला C # में आसानी से पढ़े जाने वाले कीवर्ड के बराबर है। इसे मिटाने का प्रयास एक जटिल त्रुटि उत्पन्न करता है:

Test^ t = gcnew Test();
t->obj = gcnew Example();   // Error C3892
t->obj->field = 42;         // Error C3892
Example^ another = t->obj;  // Error C2440
another->field = 42; 

हालांकि यह धूम्रपान और दर्पण है। अपरिवर्तनीयता संकलक द्वारा सत्यापित की जाती है, सीएलआर द्वारा नहीं। एक और प्रबंधित भाषा दोनों को संशोधित कर सकती है। जो समस्या की जड़ है, सीएलआर के पास इसके लिए समर्थन नहीं है।


मुझे नहीं पता

private readonly object x = 5;
x=3;

काम करेगा। लेकिन अगर ऐसा होता है, तो इसका कोई मतलब नहीं होगा।


मैं आपसे पूरी तरह सहमत हूं , और मैं कभी-कभी अपने कोड में readonly संदर्भ प्रकारों के लिए आसानी से उपयोग करता हूं।

एक उदाहरण के रूप में: मेरे पास कुछ private या protected सदस्य हो सकते हैं - कह सकते हैं, एक List<T> - जिसका उपयोग मैं एक वर्ग के तरीकों में अपने सभी परिवर्तनशील महिमा (कॉल Add , Remove , आदि) के भीतर करता हूं। मैं बस यह सुनिश्चित करने के लिए कि क्या कोई फर्क नहीं पड़ता, मैं हमेशा एक ही वस्तु के साथ काम कर रहा हूँ , एक सुरक्षा गार्ड रखना चाहता हूँ । यह मुझे और अन्य डेवलपर्स को कुछ बेवकूफ बनाने से बचाता है: अर्थात्, एक नई वस्तु के लिए सदस्य को असाइन करना।

मेरे लिए, यह अक्सर एक निजी set विधि के साथ एक संपत्ति का उपयोग करने के लिए एक बेहतर विकल्प है। क्यूं कर? क्योंकि आसानी से मतलब है कि मूल्य तात्कालिकता के बाद भी नहीं बदला जा सकता है, यहां तक ​​कि आधार वर्ग द्वारा भी

दूसरे शब्दों में, अगर मेरे पास यह था:

protected List<T> InternalList { get; private set; }

तब मैं अभी भी InternalList = new List<T>(); सेट कर सकता था InternalList = new List<T>(); मेरे आधार वर्ग में कोड में किसी भी मनमाने बिंदु पर। (यह मेरी ओर से एक बहुत ही मूर्खतापूर्ण त्रुटि की आवश्यकता होगी, हाँ; लेकिन यह अभी भी संभव होगा।)

दूसरी ओर, यह:

protected readonly List<T> _internalList;

यह स्पष्ट रूप से स्पष्ट करता है कि _internalList केवल एक विशेष वस्तु (जिस पर _internalList को _internalList में सेट किया गया है) को संदर्भित कर सकता है

तो मैं आपकी तरफ हूं। यह विचार कि एक परस्पर संदर्भ प्रकार पर आसानी से उपयोग करने से बचना चाहिए, यह मेरे लिए व्यक्तिगत रूप से निराशाजनक है, क्योंकि यह मूल रूप से readonly कीवर्ड की गलतफहमी को दूर करता है।





immutability