सार्वजनिक क्षेत्र बनाम स्वचालित गुण


353

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

लेकिन कई बार ऐसा होता है जब कोई फील्ड वैल्यू रखने के लिए होता है और उसे पाने या सेट करने के लिए किसी कंपीटिशन की जरूरत नहीं होती। इनके लिए हम सभी इस संख्या को करेंगे:

public class Book
{
    private string _title;

    public string Title
    {
          get{ return _title;  }
          set{ _title = value; }
    }
}

खैर, मेरे पास एक स्वीकारोक्ति है, मैं वह सब नहीं लिख सकता था (वास्तव में, इसे लिखना नहीं था, इसे देखना था), इसलिए मैं दुष्ट हो गया और सार्वजनिक क्षेत्रों का इस्तेमाल किया।

इसके बाद C # 3.0 आता है और मैं देखता हूं कि उन्होंने स्वचालित गुण जोड़े हैं:

public class Book
{
    public string Title {get; set;} 
}

जो स्पष्ट है, और मैं इसके लिए आभारी हूं, लेकिन वास्तव में, केवल सार्वजनिक क्षेत्र बनाने से अलग क्या है?

public class Book
{
    public string Title;
}


6
मैं एक संपत्ति के लिए एक feild बदल दिया है बस इसलिए मैं सेटर पर एक ब्रेकप्वाइंट सेट कर सकता था
इयान रिंगरोज

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

2
propकोड स्निपेट यह तेजी से गुण पैदा करने के लिए बनाता है। बस propतब टैब टाइप करें ।
टोनो नाम

जवाबों:


175

एक में संबंधित सवाल मैं कुछ समय पहले किया था, वहाँ जेफ के ब्लॉग पर एक पोस्ट करने के लिए एक लिंक, कुछ मतभेद समझा था।

गुण बनाम सार्वजनिक चर

  • परावर्तन चर बनाम संपत्तियों पर अलग-अलग काम करता है, इसलिए यदि आप प्रतिबिंब पर भरोसा करते हैं, तो सभी गुणों का उपयोग करना आसान है।
  • आप एक चर के खिलाफ डेटाबेस नहीं कर सकते।
  • किसी प्रॉपर्टी में परिवर्तन करना एक परिवर्तन है। उदाहरण के लिए:

    TryGetTitle(out book.Title); // requires a variable

24
"एक परिवर्तनशील संपत्ति में परिवर्तन एक ब्रेकिंग परिवर्तन है।" यह निश्चित रूप से केवल एक पुन: प्रयोज्य पुस्तकालय लिखते समय लागू होता है, जो अधिकांश डेवलपर्स नहीं कर रहे हैं।
स्टीवन

30
इसके अलावा, गुण, यहां तक ​​कि ऑटो-गुण भी आभासी हो सकते हैं, जहां फ़ील्ड नहीं हो सकते। इसलिए, एक आधार वर्ग में एक साधारण बैकिंग-फ़ील्ड कार्यान्वयन हो सकता है, जो कंपाइलर द्वारा एक ऑटो-प्रोप के लिए उत्पादित किया जाता है, जबकि व्युत्पन्न वर्ग अतिरिक्त सत्यापन या अन्य तर्क / गणना कर सकते हैं।
कीथ्स

28
साथ ही एक फ़ील्ड एक चर है और संदर्भ ( refया outकीवर्ड) द्वारा पारित किया जा सकता है , जबकि एक संपत्ति एक्सेसर्स की एक जोड़ी है और संदर्भ द्वारा पारित नहीं किया जा सकता है। उदाहरण के लिए bool success = TryGetMyTitle(out myBook.Title);जो उपयोग करता है outवह एक क्षेत्र के साथ काम करेगा और संपत्ति के साथ काम नहीं करेगा। यह इस बात का एक स्पष्ट उदाहरण है कि क्षेत्र से संपत्ति में परिवर्तन एक ब्रेकिंग परिवर्तन क्यों है!
जेपी स्टिग नीलसन

2
@KyleBaran नहीं, यह बहुत मायने नहीं रखता है क्योंकि एक संपत्ति एक्सेसर विधियों की एक जोड़ी है, न कि एक चर। एक सामान्य बात यह है कि स्थानीय चर घोषित करना (संभवतः संपत्ति को स्थानीय चर में रखा गया मूल्य पढ़ें), स्थानीय चर को ref/ के रूप में पास करें out, और फिर संपत्ति को स्थानीय चर के मान पर सेट करें। लेकिन तब कहा जाने वाला तरीका स्वयं संपत्ति तक पहुंच नहीं करता है, यह आपके द्वारा बनाए गए स्थानीय चर तक पहुंचता है।
जेपी स्टिग नीलसन

5
@theberserker सच है, हालांकि C # 6 में आप कर सकते हैं public int Foo { get; }जो एक ऑटो-प्रॉपर्टी को आसानी से बैकिंग फ़ील्ड के साथ बनाएगा।
माइकल स्टम

83

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

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

क्योंकि गुणों को बहुत पतले तरीकों के रूप में लागू किया जाता है, उनके मूल्यों के पढ़ने और लिखने पर ब्रेकपॉइंट्स सेट करना संभव है। इससे उन्हें खेतों के ऊपर एक बड़ा पैर मिल जाता है।


2
दस साल बाद, डेटा ब्रेकप्वाइंट यहाँ हैं, कम से कम .NET कोर :) के लिए
Luaan

72

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

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


9
मुझे यह उत्तर पसंद आया क्योंकि यह 'प्रतिबिंब', 'इंटरफ़ेस' या 'ओवरराइड' शब्दों का उपयोग नहीं करता है। ('अनुबंध' के बारे में बहुत बुरा)

65

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


1
मैं कहूंगा कि यदि आपको एक इंटरफ़ेस की आवश्यकता है जो गुणों को परिभाषित करता है, तो यह एक सार वर्ग होना चाहिए। सिर्फ इसलिए कि c # आपको इंटरफेस में गुणों को परिभाषित करने की अनुमति देता है, इसका मतलब यह नहीं है कि आपको उनका उपयोग करना चाहिए। यह खराब डिजाइन है।
ओडिस

8
@odyodyodys - मुझे यकीन नहीं है कि मैं सहमत हूं कि यह खराब डिजाइन है। कृपया अपने औचित्य की व्याख्या करें?
ज़ैद मसूद

4
@odyodyodys मैं zooone9243 से सहमत हूं: छोटा सा, डिजाइन के दृष्टिकोण से, एक संपत्ति की घोषणा करने और एक गेट्टर / सेटर जोड़ी घोषित करने के बीच कोई अंतर नहीं है (जो इंटरफेस के लिए आम बात है)।
मार्टिनस्टैटनर

22
@ zooone9243, + MartinStettner: यह 6 महीने पहले था, तब से मैंने बहुत कुछ सीखा। मैं इसे वापस ले जा रहा हूं :)
ओडिस

47

एक बड़ा अंतर जिसे अक्सर अनदेखा किया जाता है और किसी अन्य उत्तर में इसका उल्लेख नहीं किया जाता है: ओवरराइडिंग । आप संपत्तियों को आभासी घोषित कर सकते हैं और उन्हें ओवरराइड कर सकते हैं जबकि आप सार्वजनिक सदस्य क्षेत्रों के लिए ऐसा नहीं कर सकते।


10

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


10

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


8

फील्ड बनाने में कुछ भी गलत नहीं है public। लेकिन याद रखें getter/setterकि privateखेतों के साथ बनाना कोई अतिक्रमण नहीं है। IMO, यदि आप अन्य सुविधाओं के बारे में परवाह नहीं करते हैं, तो आप Propertyइसे बना सकते हैं public


1

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

यदि आप सिर्फ एक सार्वजनिक विशेषता के साथ जाते हैं तो आपके पास कम लचीलापन होगा।

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


0

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


0

मेरे पोव ने कुछ शोध किए

  1. मान्यकरण।
  2. किसी संपत्ति के व्यवहार को बदलने के लिए एक्सेसर को ओवरराइड करने की अनुमति दें।
  3. डिबगिंग का उद्देश्य। हम यह जान पाएंगे कि एक्सेसर में ब्रेकपॉइंट सेट करके प्रॉपर्टी कब और क्या बदलती है।
  4. हमारे पास एक फील्ड सेट-ओनली हो सकता है। मसलन, पब्लिक सेट () और प्राइवेट गेट ()। यह सार्वजनिक क्षेत्र के साथ संभव नहीं है।

यह वास्तव में हमें अधिक संभावना और व्यापकता देता है।

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