क्या संपत्ति के बजाय एक क्षेत्र को उजागर करने के लिए अपरिवर्तनीयता की गारंटी है?


10

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

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

तो readonlyकुछ मामलों में संपत्ति पर क्षेत्र चुनने के लिए अपरिवर्तनीय वैध कारण की गारंटी है ?

(स्पष्टीकरण के लिए, मैं निश्चित रूप से यह नहीं कह रहा हूं कि आपको हमेशा यह चुनाव करना चाहिए क्योंकि क्षेत्र फिलहाल अपरिवर्तनीय होता है, केवल तब जब यह वर्ग के डिजाइन के हिस्से के रूप में समझ में आता है और इसका अनुबंध में अपरिवर्तनीयता को शामिल करने का इरादा है। मुझे ज्यादातर इस बात पर दिलचस्पी है कि विशिष्ट मामलों के बजाय यह उचित हो सकता है या नहीं, जैसे कि जब आपको सदस्य की आवश्यकता हो interface, या आलसी-लोडिंग करना चाहते हों।)



1
@gnat, केवल "ReadOnly Property" को स्पष्ट करने के लिए, वे VB.NET शब्दावली का उपयोग कर रहे हैं, जिसका अर्थ है, बिना सेटर वाली प्रॉपर्टी, कि आसानी से फ़ील्ड। मेरे प्रश्न के प्रयोजनों के लिए, दो विकल्प जो प्रश्न की तुलना करते हैं, समकक्ष हैं- वे दोनों गुणों का उपयोग कर रहे हैं।
बेन आरोनसन

जवाबों:


6

सार्वजनिक स्थैतिक आसानी से फ़ील्ड निश्चित रूप से ठीक हैं। उन्हें कुछ स्थितियों के लिए अनुशंसित किया जाता है, जैसे कि जब आप एक नामित, निरंतर ऑब्जेक्ट चाहते हैं, लेकिन आप constकीवर्ड का उपयोग नहीं कर सकते ।

पढ़े-लिखे सदस्य क्षेत्र थोड़े पेचीदा होते हैं। सार्वजनिक सेटर के बिना किसी संपत्ति पर अधिक लाभ नहीं हुआ है, और एक बड़ा नुकसान है: फ़ील्ड इंटरफेस के सदस्य नहीं हो सकते। इसलिए यदि आप एक ठोस प्रकार के बजाय एक इंटरफ़ेस के विरुद्ध काम करने के लिए अपने कोड को रीफ़ैक्टर करने का निर्णय लेते हैं, तो आपको सार्वजनिक रूप से प्राप्तकर्ताओं के साथ अपने आसानी से फ़ील्ड को गुणों में बदलना होगा।

एक संरक्षित सेटर के बिना एक सार्वजनिक गैर-आभासी संपत्ति विरासत के खिलाफ सुरक्षा प्रदान करती है, जब तक कि विरासत वाले वर्गों को बैकिंग क्षेत्र तक पहुंच न हो। आप उस अनुबंध को बेस क्लास में पूरी तरह लागू कर सकते हैं।

वर्ग के सार्वजनिक इंटरफ़ेस को बदलने के बिना सदस्य की "अपरिवर्तनीयता" को बदलने में सक्षम नहीं होना इस मामले में बहुत बाधा नहीं है। यदि आप सार्वजनिक क्षेत्र को संपत्ति में बदलना चाहते हैं, तो यह आसानी से चला जाता है, इसके अलावा दो मामले हैं जिनसे आपको निपटना है:

  1. कुछ भी जो उस वस्तु के सदस्य को लिखता है, जैसे: object.Location.X = 4केवल Locationएक क्षेत्र है तो संभव है। यह हालांकि एक पठनीय क्षेत्र के लिए प्रासंगिक नहीं है, क्योंकि आप एक पठनीय संरचना को संशोधित नहीं कर सकते हैं। (यह मान लिया गया है Locationकि एक मूल्य प्रकार है - यदि नहीं तो यह मुद्दा वैसे भी लागू नहीं होगा क्योंकि readonlyउस तरह की चीज़ से बचाव नहीं करता है।)
  2. एक विधि के लिए कोई भी कॉल जो मान को पास करता है outया ref। फिर से, यह वास्तव में एक पठनीय क्षेत्र के लिए प्रासंगिक नहीं है, क्योंकि outऔर refपैरामीटर संशोधित होते हैं, और यह एक संकलक त्रुटि है वैसे भी बाहर या रेफ के रूप में एक सामयिक मूल्य पारित करने के लिए।

दूसरे शब्दों में, हालाँकि एक रीडोनॉली फ़ील्ड को आसानी से प्रॉपर्टी में परिवर्तित करने से बाइनरी संगतता टूट जाती है, अन्य स्रोत कोड को केवल इस परिवर्तन को संभालने के लिए किसी भी परिवर्तन के बिना recompiled करने की आवश्यकता होगी। यह गारंटी को तोड़ने के लिए वास्तव में आसान बनाता है।

मुझे readonlyसदस्य क्षेत्र के लिए कोई लाभ नहीं दिखता है , और एक इंटरफ़ेस पर उस तरह की अक्षमता मेरे लिए एक नुकसान के लिए पर्याप्त है कि मैं इसका उपयोग नहीं करूंगा।


ब्याज से बाहर, क्यों कर रहे हैं सार्वजनिक स्थिर केवल पढ़ने के लिए ठीक क्षेत्रों? क्या यह सिर्फ इसलिए है क्योंकि उदाहरणों के तरीकों पर निर्णय लेने से अपरिवर्तनीय क्षेत्रों (जैसे हिट-काउंटिंग, आलसी-लोडिंग, आदि) पर गुणों के उपयोग के अधिकांश मामलों को हटा दिया जाता है?
बेन एरनसन

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

2

मेरे अनुभव से, readonlyकीवर्ड वह जादू नहीं है जिसके लिए वह वादा करता है।

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

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

इस तकनीकी सीमा को C # के डिजाइनरों द्वारा स्वीकार किया गया है, और भविष्य के संस्करण में तय किया जा सकता है। लेकिन जब तक यह तय नहीं हो जाता, तब तक इसका उपयोग readonlyअधिक प्रतिबंधात्मक है और कुछ खराब कोडिंग शैली को प्रोत्साहित कर सकता है (निर्माण विधि में सब कुछ डालते हुए)।

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


1
मैं कंस्ट्रक्टरों को सरल रखना पसंद करता हूं - देखें brendan.enrick.com/post/… , blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple तो वास्तव में, अच्छी तरह से कोडिंग शैली को प्रोत्साहित करता है
एलेक्सफॉक्सगिल

1
एक निर्माता एक readonlyक्षेत्र को outया refअन्य तरीकों से पैरामीटर के रूप में पारित कर सकता है , जो तब फिट होने के लिए इसे संशोधित करने के लिए स्वतंत्र होगा।
सुपरकैट

1

फ़ील्ड हमेशा कार्यान्वयन विवरण हैं। आप अपने कार्यान्वयन के विवरण को उजागर नहीं करना चाहते हैं।

सॉफ्टवेयर इंजीनियरिंग का एक मौलिक सिद्धांत यह है कि हम यह नहीं जानते कि भविष्य में क्या आवश्यकताएं होंगी। हालांकि आपका readonlyक्षेत्र आज अच्छा हो सकता है, लेकिन यह सुझाव देने के लिए कुछ भी नहीं है कि यह कल की आवश्यकताओं का एक हिस्सा होगा। क्या होगा अगर कल यह निर्धारित करने के लिए हिट काउंटर को लागू करने की आवश्यकता है कि उस क्षेत्र को कितनी बार एक्सेस किया गया है? यदि आपको उप-वर्गों को क्षेत्र को ओवरराइड करने की अनुमति देने की आवश्यकता है तो क्या होगा?

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

सिर्फ इसलिए कि हम भाषा के साथ कुछ कर सकते हैं इसका मतलब यह नहीं है कि हमें भाषा के साथ कुछ करना चाहिए

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


1
मैं भविष्य के लचीलेपन में निर्माण के महत्व को समझता हूं, लेकिन निश्चित रूप से अगर मैं एक वर्ग लिखता हूं, जैसे, Rationalसार्वजनिक, अपरिवर्तनीय Numeratorऔर Denominatorसदस्यों के साथ, मुझे बहुत विश्वास हो सकता है कि उन सदस्यों को आलसी-लोडिंग या हिट काउंटर की आवश्यकता नहीं होगी या समान?
बेन आरोनसन

लेकिन क्या आप आश्वस्त हो सकते हैं कि कार्यान्वयन के floatलिए प्रकारों का उपयोग करके Numeratorऔर Denominatorउन्हें बदलने की आवश्यकता नहीं होगी doubles?
स्टीफन

1
खैर, एर, नहीं, वे निश्चित रूप से न तो होना चाहिए और न floatही double। उन्हें होना चाहिए int, longया BigInteger। शायद उन लोगों को बदलने की जरूरत है ... लेकिन अगर उन्हें सार्वजनिक इंटरफ़ेस में भी बदलाव करने की आवश्यकता होती है, तो वास्तव में गुणों का उपयोग करने से उस विस्तार के आसपास कोई एनकैप्सुलेशन नहीं होता है।
बेन आरोनसन

-3

नहीं, यह कोई औचित्य नहीं है।

एक औचित्य की गारंटी के रूप में पठनीयता का उपयोग करना हैक की तरह अधिक नहीं है।

जब वेरिएबल डिफाइन किया जाता है, तो रीडियनली का अर्थ है एक कंस्ट्रक्टर ओ द्वारा असाइन किया गया।

मुझे लगता है कि यह एक बुरा अभ्यास होगा

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

सरल इंटरफ़ेस उदाहरण: यहां छवि विवरण दर्ज करें


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