क्या C # में निजी गुणों का उपयोग करने के कोई कारण हैं?


245

मुझे बस एहसास हुआ कि C # प्रॉपर्टी कंस्ट्रक्शन का उपयोग निजी एक्सेस संशोधक के साथ भी किया जा सकता है :

private string Password { get; set; }

हालांकि यह तकनीकी रूप से दिलचस्प है, मैं कल्पना नहीं कर सकता कि मैं इसका उपयोग कब करूंगा क्योंकि एक निजी क्षेत्र में भी कम समारोह शामिल है :

private string _password;

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

private string Password { get; }

या

private string Password { set; }

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

क्या कोई किसी कारण से C # में निजी संपत्तियों का उपयोग करता है या क्या यह तकनीकी रूप से संभव-अभी तक शायद ही कभी इस्तेमाल किया गया वास्तविक-कोड निर्माण में से एक है?

परिशिष्ट

अच्छे उत्तर, उनके माध्यम से पढ़कर मैंने निजी संपत्तियों के लिए इन उपयोगों को रद्द कर दिया:

  • जब निजी क्षेत्रों को आलसी लोड करने की आवश्यकता होती है
  • जब निजी क्षेत्रों को अतिरिक्त तर्क की आवश्यकता होती है या उनकी गणना की जाती है
  • चूंकि निजी क्षेत्रों को डिबग करना मुश्किल हो सकता है
  • "अपने आप को एक अनुबंध प्रस्तुत करने के लिए"
  • आंतरिक रूप से परिवर्तित / सरलीकरण के हिस्से के रूप में एक उजागर संपत्ति को सरल बनाना
  • रैपिंग ग्लोबल वैरिएबल का उपयोग आपकी कक्षा के अंदर किया जाएगा

निजी संपत्तियों द्वारा प्रोत्साहित की गई तकनीक सेल्फ इनकैप्सुलेशन है - देखें: sourcemaking.com/refactoring/self-encapsulate-field
LBushkin

जवाबों:


212

अगर मैं किसी मूल्य को कैश करना चाहता हूं और इसे लोड करना चाहता हूं तो मैं उनका उपयोग करता हूं।

private string _password;
private string Password
{
    get
    {
        if (_password == null)
        {
            _password = CallExpensiveOperation();
        }

        return _password;
    }
}

42
इसके लिए एक अच्छा सामान्य पैटर्न हैreturn _password ?? (_password = CallExpensiveOperation());
मार्क

1
यदि आप इसका उपयोग कर सकते हैं तो @Evlex Lazy <T> बेहतर हो सकता है। लेकिन यह केवल स्थैतिक सामान का उपयोग कर सकता है, इसलिए आप (गैर-स्थैतिक) तरीकों या अन्य सदस्यों तक नहीं पहुंच सकते। वैसे मैं return _password ?? (_password = CallExpensiveOperation());थोड़ी देर से सिंगल लाइन सिंटैक्स पसंद करता हूं । या वास्तव में Resharper इसे पसंद करता है :)।
बार्ट

4
@Marc C # 6 के बाद से आपको रिटर्न और रिटर्न लिखना भी नहीं आता है। private string Password => _password ?? (_password = CallExpensiveOperation());
ओटो एब्नॉर्मलब्रैब्रुचर

1
C # 8 के साथ यह और भी छोटा है:private string Password => _password ??= CallExpensiveOperation();
डेव एम

2
@Bas यह आलसी लोडिंग नहीं है क्योंकि CallExpensiveOperation();निर्माण के दौरान कहा जाता है / युक्त वस्तु के आरंभीकरण के लिए और न कि जब संपत्ति पहली बार एक्सेस की जाती है।
स्टीफन पोडस्कुबका

142

मेरे कोड में इसका प्राथमिक उपयोग आलसी इनिशियलाइज़ेशन है, जैसा कि अन्य लोगों ने उल्लेख किया है।

खेतों पर निजी संपत्तियों के लिए एक और कारण यह है कि निजी संपत्तियां बहुत हैं, निजी क्षेत्रों की तुलना में डिबग करना बहुत आसान है। मैं अक्सर ऐसी चीजों को जानना चाहता हूं जैसे "यह क्षेत्र अप्रत्याशित रूप से सेट हो रहा है? कौन पहला कॉलर है जो इस क्षेत्र को सेट करता है?" और यह आसान है अगर आप बस सेटर और हिट गो पर एक ब्रेकपॉइंट लगा सकते हैं। आप वहां लॉगिंग डाल सकते हैं। आप प्रदर्शन मीट्रिक वहां डाल सकते हैं। आप डिबग बिल्ड में चलने वाली निरंतरता जाँच में रख सकते हैं।

असल में, यह नीचे आता है: कोड डेटा से कहीं अधिक शक्तिशाली है । कोई भी तकनीक जो मुझे उस कोड को लिखने देती है जिसकी मुझे आवश्यकता है वह एक अच्छा है। फ़ील्ड्स आपको उनमें कोड लिखने की अनुमति नहीं देते हैं, गुण करते हैं।


5
क्या "कोड डेटा से कहीं अधिक शक्तिशाली है" आपका कहना है? Googling यह आपके लिए इंगित करने वाले संदर्भ देता है। बस इतना जानना चाहता हूं कि जरूरत पड़ने पर मैं इसे सही तरीके से उद्धृत कर सकता हूं।
जोन वेंज

24
@ जोआन: मुझे नहीं पता। या तो मैंने इसे बनाया, या मैंने किसी और को यह कहते सुना और सोचा कि "वाह, मुझे पूरी तरह से चोरी करनी चाहिए, और फिर उन सभी के बारे में भूल जाना चाहिए जिन्हें मैंने इसे चुरा लिया है।"
एरिक लिपर्ट

1
+ CodeLens आपको बताता है कि संपत्ति कहाँ संदर्भित है
UUDdLrLrSs

43

शायद नेस्टेड / इनहेरिट की गई कक्षाओं के साथ एक उपयोग का मामला है या शायद जहां संपत्ति के मूल्य को वापस देने के बजाय एक गेट / सेट में तर्क हो सकता है।

मैं व्यक्तिगत रूप से इसका उपयोग तब भी करता हूं, जब मुझे किसी संपत्ति के गेट्टर या सेटर पर तर्क की आवश्यकता नहीं होती है। एक संपत्ति का उपयोग करना, यहां तक ​​कि एक निजी भी, आपके कोड को भविष्य-प्रूफ करने में मदद करता है ताकि आवश्यकता पड़ने पर आप तर्क को बाद में एक गेटर में जोड़ सकें।

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


एक अर्ध-संबंधित मामले में (हालांकि आपके प्रश्न से अलग), मैं अक्सर सार्वजनिक संपत्तियों पर निजी बसने वालों का उपयोग करता हूं:

public string Password 
{
    get; 
    private set;
}

यह आपको एक सार्वजनिक गेट्टर देता है, लेकिन सेटर को निजी रखता है।


+1 समझ में आता है: "अगर मुझे लगता है कि एक संपत्ति को अंततः अतिरिक्त तर्क की आवश्यकता हो सकती है, तो मैं कभी-कभी इसे एक क्षेत्र का उपयोग करने के बजाय एक निजी संपत्ति में लपेट दूंगा, बस इसलिए मुझे बाद में अपना कोड नहीं बदलना पड़ेगा।"
एडवर्ड तुंगाय जुले

7
निजी
बसाने

20

निजी के लिए एक अच्छा उपयोग केवल गुण मानों की गणना है। कई बार मेरे पास ऐसे गुण होते हैं जो निजी रूप से पढ़े जाते हैं और सिर्फ मेरे प्रकार के अन्य क्षेत्रों की गणना करते हैं। यह एक विधि के योग्य नहीं है और अन्य वर्गों के लिए दिलचस्प नहीं है इसलिए यह निजी संपत्ति है।


20

आलसी इनिशियलाइज़ेशन एक जगह है जहाँ वे साफ-सुथरे हो सकते हैं, जैसे

private Lazy<MyType> mytype = new Lazy<MyType>(/* expensive factory function */);

private MyType MyType { get { return this.mytype.Value; } }

// In C#6, you replace the last line with: private MyType MyType => myType.Value;

तब आप लिख सकते हैं: this.MyTypeहर जगह के बजाय this.mytype.Valueऔर इस तथ्य को घेरना कि यह एक ही स्थान पर आलसी है।

एक शर्म की बात यह है कि C # बैकिंग फ़ील्ड को संपत्ति में स्कैन करने का समर्थन नहीं करता है (अर्थात इसे संपत्ति परिभाषा के अंदर घोषित करते हुए) इसे पूरी तरह से छिपाने और यह सुनिश्चित करने के लिए कि इसे केवल संपत्ति के माध्यम से कभी भी एक्सेस किया जा सकता है।


2
इससे सहमत होना होगा कि वहां का पहलू भी होगा।
क्रिस मैरिकिक

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

5
@Eric Lippert - field-declarationभीतर scoped रहा है accessor-declarationsएक लंबे समय के लिए मेरी सी # इच्छा सूची पर नंबर 1 स्थान दिया गया है। यदि आप उस डिज़ाइन और कार्यान्वित को कुछ (वास्तविक) भविष्य के संस्करण में प्राप्त कर सकते हैं, तो मैं आपको एक केक बेक कर दूंगा।
जेफरी एल वाइटलेज

13

केवल एक उपयोग जो मैं सोच सकता हूं

private bool IsPasswordSet 
{ 
     get
     {
       return !String.IsNullOrEmpty(_password);
     }
}

अन्य निजी चर से गणना की जाने वाली संपत्तियों के उपयोगी वर्ग के लिए +1
डैरन थॉमस

2
क्यों नहीं एक निजी विधि का उपयोग करेंprivate bool IsPasswordSet() { return !String.IsNullOrEmpty(_password); }
रोमन

10

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

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


+1: "आप अपने आप को बहुत ही समान कारणों से एक अनुबंध भी पेश कर सकते हैं" समझ में आता है
एडवर्ड टंगू

8

मैं उन्हें क्रमांकन में उपयोग करता हूं, जैसे कि DataContractSerializerप्रोटोबुफ़-नेट जैसी चीजें जो इस उपयोग का समर्थन XmlSerializerकरती हैं ( नहीं)। यदि आप क्रमांकन के भाग के रूप में किसी वस्तु को सरल बनाना चाहते हैं तो यह उपयोगी है:

public SomeComplexType SomeProp { get;set;}
[DataMember(Order=1)]
private int SomePropProxy {
    get { return SomeProp.ToInt32(); }
    set { SomeProp = SomeComplexType.FromInt32(value); }
}

6

एक चीज जो मैं करता हूं वह है "वैश्विक" चर / कैश को स्टोर करना HttpContext.Current

private static string SomeValue{
  get{
    if(HttpContext.Current.Items["MyClass:SomeValue"]==null){
      HttpContext.Current.Items["MyClass:SomeValue"]="";
    }
    return HttpContext.Current.Items["MyClass:SomeValue"];
  }
  set{
    HttpContext.Current.Items["MyClass:SomeValue"]=value;
  }
}

5

मैं उन्हें हर अब और फिर उपयोग करें। वे चीजों को डिबग करना आसान बना सकते हैं जब आप आसानी से संपत्ति में एक ब्रेकपॉइंट में डाल सकते हैं या आप लॉगिंग स्टेटमेंट आदि जोड़ सकते हैं।

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


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

5

मैं निजी संपत्तियों का उपयोग उप-संपत्तियों तक पहुंचने के लिए कोड को कम करने के लिए करता हूं जो अक्सर उपयोग करते हैं।

    private double MonitorResolution
    {
        get { return this.Computer.Accesories.Monitor.Settings.Resolution; }
    }

यह उपयोगी है अगर कई उप गुण हैं।


2

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


2

संपत्ति सेट या प्राप्त (तर्क आलसी आरंभीकरण) के साथ जुड़े तर्क होने पर यह सही समझ में आता है और संपत्ति का उपयोग कक्षा में कुछ स्थानों पर किया जाता है।

अगर यह सिर्फ एक सीधे समर्थन क्षेत्र है? अच्छे कारण के रूप में कुछ भी दिमाग में नहीं आता है।


2

मुझे पता है कि यह प्रश्न बहुत पुराना है, लेकिन नीचे दी गई जानकारी किसी भी मौजूदा उत्तर में नहीं थी।

मैं कल्पना नहीं कर सकता कि मुझे कभी आंतरिक रूप से सक्षम होने की आवश्यकता होगी लेकिन सेट नहीं

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

साथ ही विजुअल स्टूडियो प्रोफेशनल एक प्रॉपर्टी के बारे में जानकारी देगा न कि एक फील्ड जिससे यह देखना आसान हो जाए कि आपके फील्ड का क्या उपयोग किया जा रहा है।

PorpField


1

ठीक है, जैसा कि किसी ने भी उल्लेख नहीं किया है आप इसका उपयोग डेटा को मान्य करने या चर को लॉक करने के लिए कर सकते हैं।

  • मान्यकरण

    string _password;
    string Password
    {
        get { return _password; }
        set
        {
            // Validation logic.
            if (value.Length < 8)
            {
                throw new Exception("Password too short!");
            }
    
            _password = value;
        }
    }
  • ताला

    object _lock = new object();
    object _lockedReference;
    object LockedReference
    { 
        get
        {
            lock (_lock)
            {
                return _lockedReference;
            }
        }
        set
        {
            lock (_lock)
            {
                _lockedReference = value;
            }
        }
    }

    नोट: एक संदर्भ को लॉक करते समय आप संदर्भित ऑब्जेक्ट के सदस्यों तक पहुंच को लॉक नहीं करते हैं।

आलसी संदर्भ: जब आलसी लोड हो रहा हो, तो आपको इसे समाप्त करने की आवश्यकता हो सकती है जिसके लिए आजकल AsyncLazy है । यदि आप Visual Studio SDK 2015 की तुलना में पुराने संस्करणों पर हैं या इसका उपयोग नहीं कर रहे हैं, तो आप AsyncEx के AsyncLazy का उपयोग भी कर सकते हैं ।


0

स्पष्ट क्षेत्रों के कुछ और अधिक विदेशी उपयोगों में शामिल हैं:

  • आपको उपयोग करने की आवश्यकता है refया outमूल्य के साथ - शायद क्योंकि यह एक Interlockedकाउंटर है
  • इसका उद्देश्यstruct स्पष्ट लेआउट के साथ उदाहरण के लिए मौलिक लेआउट का प्रतिनिधित्व करना है (शायद C ++ डंप, या unsafeकोड पर मैप करने के लिए)
  • ऐतिहासिक रूप से प्रकार का उपयोग BinaryFormatterस्वचालित फ़ील्ड हैंडलिंग के साथ किया गया है (ऑटो-प्रॉप में परिवर्तन से नाम बदलते हैं और इस प्रकार धारावाहिक को तोड़ते हैं)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.