क्या आपको निजी संपत्तियां बनानी चाहिए?


19
private string mWhatever;

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = value;
    }
}

मैंने कुछ ऐसे लोगों को देखा है जो हर एक सदस्य के लिए संपत्ति बनाते हैं, निजी या नहीं ... क्या इसका कोई मतलब है? मैं इसे 1% मामलों में समझदारी से देख सकता था जब आप उस वर्ग के अंदर के सदस्य तक पहुँच को नियंत्रित करना चाहते थे क्योंकि अगर आपने हर सदस्य के लिए गुणों का उपयोग नहीं किया तो यह विसंगतियों और जाँच को जन्म देगा। सदस्य की पहुंच है या नहीं (क्योंकि आपके पास कक्षा के दायरे में दोनों की पहुंच है)।

जवाबों:


17

संक्षिप्त उत्तर: हां , जब जरूरत हो। अन्यथा, एक ऑटो-इम्प्लीमेंटेड प्रॉपर्टी गेट्टर और सेटर का उपयोग करेंprivate string Whatever { get; set;}

  • जब आप एक करीबी डोमेन दृष्टिकोण का उपयोग कर रहे हैं तो यह बहुत आसान है
  • जब आप मान सेट कर रहे हों तो एक विशिष्ट तर्क की जाँच की जानी चाहिए

जब आप निजी बसने वालों का उपयोग कर रहे होंगे, तो इसका पूरा विवरण है: C # संपत्ति का उपयोग


यदि आवश्यक हो तो संपत्ति को बाद में सार्वजनिक करना भी वास्तव में आसान है।
टॉम अचार

4
एक करीबी डोमेन दृष्टिकोण क्या है ?
त्रिशूल

1
मैं क्लास की एक प्रॉपर्टी में एक प्राइवेट सेटर की बात कर रहा था। यह ऑब्जेक्ट से मान सेट करने के लिए सीधी पहुंच को रोकना चाहिए और मूल्य निर्धारित करने से पहले कुछ लॉजिक चेक की सुविधा प्रदान करना चाहिए।
युसुबोव

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

12

कुछ अच्छे उत्तर यहाँ पहले से ही हैं, लेकिन मुझे लगता है कि उनमें से अधिकांश आपके प्रश्न के एक बिंदु को याद करते हैं:

मैंने कुछ ऐसे लोगों को देखा है जो हर एक सदस्य के लिए संपत्ति बनाते हैं, निजी या नहीं ... क्या इसका कोई मतलब है?

मुझे लगता है कि यह शायद ही कभी पहले से ही आवश्यक है , हर एक सदस्य के लिए । के साथ शुरू

 private string Whatever;

जब आप बाद में एक ऐसे बिंदु पर आते हैं, जहां आपको इस विशिष्ट सदस्य के लिए इनकैप्सुलेशन या एक सशर्त ब्रेकप्वाइंट की आवश्यकता होती है , तो आप अभी भी इसे एक ही नाम से एक संपत्ति द्वारा बदल सकते हैं - अधिकांश मामलों में कोड को बदलने के बिना जो उपयोग करता है Whatever। लेकिन सावधान रहें, सूक्ष्म अंतर हैं, इस एसओ पोस्ट में ब्रायन रासमुसेन का जवाब (इमाम करीम, +1 द्वारा दिया गया लिंक भी देखें)।


+1, भी, आप सही हैं, अधिकांश उत्तर मूल प्रश्न अंकों से चूक गए, हम विशिष्ट हैं आईटी लोग :)
NoChance

एक संपत्ति के बाद एक क्षेत्र को फिर से दिखाना एक दुःस्वप्न है; आप सभी उपभोक्ताओं को फिर से संगठित करने की आवश्यकता है। कस्टम तर्क रखने के लिए एक स्वचालित संपत्ति बदलना एक हवा है। यदि रिफैक्टर को देखने पर कोड की थोड़ी सी भी संभावना है, तो यह बहुत कम काम होने वाला है यदि आप सिर्फ शुरुआत से ही संपत्तियों का उपयोग करते हैं।
दान

@ दान: ज्यादातर परियोजनाओं में मैंने देखा है कि प्रयास काफी समान है, आपको दोनों मामलों में फिर से जुटना होगा । फिर भी मुझे लगता है कि आप सही हैं कि गुणों का उपयोग करते हुए, विशेष रूप से ऑटो गुण, प्रतिबिंब के साथ कुछ सूक्ष्म समस्याओं या "बाहर" मापदंडों में सदस्य चर के उपयोग से बचने में मदद कर सकते हैं।
डॉक ब्राउन

@DocBrown किसी भी मामले में, यह निश्चित रूप से एक कैच-ऑल स्टेटमेंट नहीं है। इसे सरल रखने और एक क्षेत्र का उपयोग करने के बहुत सारे कारण हैं। यदि आप एक रिफ्लेक्टर की भविष्यवाणी कर सकते हैं, तो भी सूक्ष्म समस्याएं विचार करने लायक हैं।
दान

7

इस दृष्टिकोण का सबसे बड़ा लाभ यह है कि जब आपके चर बदलते हैं तो आपको नियंत्रण मिलता है ।

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

संपत्ति के साथ, आप एक सेटर में एक विराम बिंदु निर्धारित कर सकते हैं । एक शर्त के साथ संयुक्त, यह एक ही रन में नीचे हो सकता है।

VC ++ में डेटा ब्रेकप्वाइंट है , लेकिन यह केवल अनवांटेड कोड के लिए उपलब्ध है।


1

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


1

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


हालांकि दिया गया उदाहरण एक गरीब है। बॉयलरप्लेट संपत्ति पाने वाले और इस तरह बसने वाले लगभग हमेशा एक बुरा विचार होते हैं। यदि आप C # 3.0 या बाद में उपयोग कर रहे हैं, तो ऑटो गुण एक बेहतर विचार हैं:

private string Whatever { get; set; };

यह छोटा है, क्लीनर है, और बहुत अधिक पठनीय है। वास्तव में यह केवल बैकिंग चर घोषित करने की तुलना में मुश्किल से लंबा है।

सबसे महत्वपूर्ण बात यह है कि, बाकी कार्यक्रमों के शब्दार्थों को बदलने के बिना किसी भी समय ऑटो गुणों को पूर्ण गुणों में परिवर्तित किया जा सकता है! इस प्रकार यदि आपको सत्यापन या त्रुटि को जोड़ने की आवश्यकता है, तो आप ऐसा आसानी से कर सकते हैं।


यह है के रूप में, मैं हमेशा सोचा था कि यह शर्म की बात थी तुम, एक ही संपत्ति को पढ़ने के लिए नहीं कर सकता है कि केवल निर्माता में मूल्य में लिखने के लिए सक्षम किया जा रहा लागू करने के लिए, (मैं अपरिवर्तनीय प्रकार पसंद करते हैं ), लेकिन यह सी # 6.0 में जोड़ा गया है के रूप में "ऑटो-प्रॉपर्टी इनिशियलाइज़र", जो आपको करने की अनुमति देता है:

private string Whatever { get; } = ...;

या

private string Whatever { get; };

साथ में

    Whatever = ...;

कंस्ट्रक्टर में।


0

यह निजी संपत्तियों के लिए ऐसा करने के लिए बिल्कुल आवश्यक नहीं है, लेकिन यह संशोधित करने की अनुमति देता है कि संपत्ति कैसे प्राप्त की जाती है या अंतर्निहित मूल्य को बिना परिवर्तित किए कैसे सेट किया जाता है।

उदाहरण के लिए, अंतर्निहित मान सेट करने का तरीका संशोधित करता है:

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = string.IsNullOrEmpty(value) ? string.Empty : value;
    }
}

0

हाँ

मैं व्यक्तिगत रूप से इसे कैशिंग तंत्र के रूप में उपयोग करता हूं, और हम इसे संपत्ति-स्तरीय कैशिंग कह सकते हैं

private List<User> users;
private List<User> Users
{
    get
    {
        if(users == null) users = new UserManager().GetUsers();
        return users;
    }
}

अब मेरी कक्षा के अंदर अन्य स्थानों पर, मैं फ़ील्ड के Usersबजाय संपत्ति का उपयोग करता हूं users

एक और व्यवहार्य स्थिति तब हो सकती है जब आप किसी क्षेत्र पर कुछ तर्क को लागू करना चाहते हैं, लेकिन एक कक्षा में केंद्रीकृत तरीके से। इस प्रकार आप क्षेत्र के लिए एक GetFoo()विधि, या एक Fooसंपत्ति दोनों बना सकते हैं foo

private string foo;
private string Foo
{
    get
    {
        return "Mr. " + foo;
    }
}

0

कुछ और विचार करने के लिए:

वास्तविक गुण एक कार्यान्वयन विवरण हैं। ओओपी के लक्ष्यों में से एक कार्यान्वयन विवरणों के जोखिम को कम करने की कोशिश करना है जहां व्यावहारिक है।

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

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

बेशक, अगर क्लास के बाहर किसी भी चीज के लिए कोई नकारात्मक परिणाम नहीं है, सीधे किसी संपत्ति तक पहुंचने में सक्षम है, तो आपको इसे सार्वजनिक करना चाहिए। हालाँकि मेरे अनुभव में, इस तरह के मामले अपेक्षाकृत कम और बीच के हैं।


0

मुझे पता है कि यह एक पुराना सवाल है और सब कुछ @Yusubov ने कहा कि सही है, लेकिन सेटर में विशिष्ट तर्क के बारे में उनकी दूसरी बुलेट बिंदु के संबंध में, और जब से मैंने किसी को विशेष रूप से इसका उल्लेख नहीं देखा, तब एक आदर्श उदाहरण तब होगा जब आपकी कक्षा होगी INotifyPropertyChangedइंटरफ़ेस लागू करता है।

यह WCF और सिल्वरलाइट में एक टन का उपयोग किया जाता है जो आपको यह जानने की अनुमति देता है कि जब किसी विशिष्ट संपत्ति को उसके सेटर में तर्क के माध्यम से बदल दिया गया है जैसे नीचे वर्ग में:

public class Settings : INotifyPropertyChanged
{
    public Settings() 
    { 
        this.CountryField = String.Empty; 
    }

    private string CountryField;
    public string Country
    {
        get { return this.CountryField; }
        set
        {
            if (Object.ReferenceEquals(this.CountryField, value)) { return; }

            this.CountryField = value;
            this.RaisePropertyChanged("Country");
        } 
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.