एक क्षेत्र और एक संपत्ति के बीच अंतर क्या है?


1129

C # में, किसी प्रॉपर्टी से किसी फ़ील्ड को अलग क्या बनाया जाता है, और प्रॉपर्टी के बजाय फ़ील्ड का उपयोग कब किया जाना चाहिए?


32
Microsoft सीधे अपने सदस्य डिजाइन दिशानिर्देशों के भाग के रूप में (सभी .NET भाषाओं के लिए) इस प्रश्न का उत्तर देता है । बारीकियों के लिए लेख देखें संपत्ति डिज़ाइन और फ़ील्ड डिज़ाइन । ध्यान दें कि उदाहरण के सदस्यों और स्थिर सदस्यों के बीच एक अंतर है ।
डेविड आरआर

जवाबों:


979

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

public class MyClass
{
    // this is a field.  It is private to your class and stores the actual data.
    private string _myField;

    // this is a property. When accessed it uses the underlying field,
    // but only exposes the contract, which will not be affected by the underlying field
    public string MyProperty
    {
        get
        {
            return _myField;
        }
        set
        {
            _myField = value;
        }
    }

    // This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
    // used to generate a private field for you
    public int AnotherProperty{get;set;} 
}

@Kent बताते हैं कि प्रॉपर्टी को फ़ील्ड्स को एन्कैप्सुलेट करने की आवश्यकता नहीं है, वे अन्य फ़ील्ड्स पर कैलकुलेशन कर सकते हैं, या अन्य उद्देश्यों की सेवा कर सकते हैं।

@ जीएसएस बताता है कि आप अन्य तर्क भी कर सकते हैं, जैसे कि सत्यापन, जब एक संपत्ति तक पहुँचा जाता है, तो एक और उपयोगी सुविधा।


185
यह ध्यान देने योग्य है कि खेतों को घेरने के लिए गुणों की आवश्यकता नहीं है। संपत्ति के पीछे कोई क्षेत्र नहीं हो सकता है। यह एक गणना हो सकती है या एक स्थिर या जो कुछ भी हो उसे वापस कर सकती है।
कैंट बूगार्ट

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

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

6
@jpaugh यदि मैं एक वर्ग उपभोक्ता हूं, तो मैं कक्षा निर्माता द्वारा निर्धारित अनुबंधों का पालन करता हूं। यदि कोई संपत्ति है string, तो मेरा अनुबंध है: ~ 2bil लंबाई तक किसी भी चार्ट को असाइन करें। यदि कोई संपत्ति है DateTime, तो मेरा अनुबंध है: DateTime की सीमाओं के भीतर कोई भी संख्या निर्दिष्ट करें, जिसे मैं देख सकता हूं। यदि रचनाकार बस्तियों में बाधाओं को जोड़ता है, तो उन बाधाओं का संचार नहीं किया जाता है। लेकिन अगर, इसके बजाय, निर्माता से प्रकार बदलता stringहै Surname, तो उनका नया उपनाम वर्ग बाधाओं का संचार करता है, और संपत्ति public Surname LastNameमें सेटर सत्यापन नहीं होता है। इसके अलावा, Surnameपुन: प्रयोज्य है।
सुमेर

4
और जब से Surname, मेरे उदाहरण में, पुन: प्रयोज्य है, आपको कोड में अन्य स्थानों पर एक संपत्ति सेटर में उन मान्यताओं की प्रतिलिपि बनाने / चिपकाने के बारे में बाद में चिंता करने की आवश्यकता नहीं है। न ही अगर सरनेम के लिए व्यावसायिक नियमों में कोई बदलाव किया जाए तो सरनेम का सत्यापन कई स्थानों पर है। मान ऑब्जेक्ट के बारे में पोस्ट किए गए लिंक को देखें
Suamere

261

ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग सिद्धांतों का कहना है कि, एक वर्ग के आंतरिक कामकाज को बाहरी दुनिया से छिपाया जाना चाहिए। यदि आप एक क्षेत्र को उजागर करते हैं तो आप कक्षा के आंतरिक कार्यान्वयन को उजागर कर रहे हैं। इसलिए हम अपने पर निर्भर कोड को तोड़ने के बिना कार्यान्वयन को बदलने की क्षमता देने के लिए (या जावा के मामले में तरीकों) के साथ खेतों को लपेटते हैं। यह देखने के रूप में कि हम संपत्ति में तर्क रख सकते हैं, हमें अनुमति तर्क आदि का प्रदर्शन करने की अनुमति देता है यदि हमें इसकी आवश्यकता है। C # 3 में संभवतः ऑटोप्रोप्ट्टी की भ्रामक धारणा है। यह हमें केवल संपत्ति को परिभाषित करने की अनुमति देता है और सी # 3 संकलक हमारे लिए निजी क्षेत्र उत्पन्न करेगा।

public class Person
{
   private string _name;

   public string Name
   {
      get
      {
         return _name;
      }
      set
      {
         _name = value;
      }
   }
   public int Age{get;set;} //AutoProperty generates private field for us
}

89
ऑटोपोपरेटी का उल्लेख करने के लिए +1 - मुझे लगता है कि यह कुछ ऐसा है जिसके जवाब यहाँ (और अन्य जगहों पर) दिए गए हैं। इस स्पष्टीकरण के बिना, यह अभी भी समझ पाना बहुत मुश्किल हो सकता है कि public int myVar { get; set; }वास्तव में इसका क्या मतलब है (और मुझे लगता है कि यह कारण है कम से कम 50% हिट यह सवाल हो जाता है)।
प्रियादु नीमरे

7
+1 ऑटो का उल्लेख करने के लिए भी, और यह उल्लेख करने के लिए कि यह कैसे काम करता है ("ऑटोप्रॉपर्टी हमारे लिए निजी क्षेत्र उत्पन्न करता है") यह वह उत्तर था जो मैं एक प्रश्न की तलाश में था। शोध करते समय मैंने MSDN के पृष्ठ पर उनके बारे में कोई संकेत नहीं देखा कि एक निजी क्षेत्र बनाया गया था और भ्रम पैदा कर रहा था। मुझे लगता है कि इसका क्या मतलब है? "विशेषताओं को ऑटो-कार्यान्वित गुणों पर अनुमति दी जाती है लेकिन स्पष्ट रूप से बैकिंग फ़ील्ड्स पर नहीं क्योंकि वे आपके स्रोत कोड से सुलभ नहीं हैं। यदि आपको किसी संपत्ति के बैकिंग फ़ील्ड पर एक विशेषता का उपयोग करना चाहिए, तो बस एक नियमित संपत्ति बनाएं।" लेकिन यकीन नहीं था।
Nyra

3
ध्यान दें कि दिया गया उदाहरण स्क्वाट को एनकैप्सुलेट नहीं करता है। यह संपत्ति निजी क्षेत्र में 100% पूर्ण पहुंच प्रदान करती है, इसलिए यह वस्तु-उन्मुख नहीं है। आपके पास इस मामले में सार्वजनिक क्षेत्र हो सकता है। दी गई, यह भविष्य में कोड को रिफलेक्टर करने में (मामूली) मदद करती है, लेकिन इसके लायक कोई भी IDE कुछ कीस्ट्रोक्स वाली फ़ील्ड को संपत्ति में बदल सकती है। यह उत्तर तकनीकी रूप से सही हो सकता है कि गुण कैसे काम करते हैं, लेकिन यह उनके उपयोग के लिए एक अच्छा "ओओपी स्पष्टीकरण" नहीं देता है।
सारा

2
@kai मैं सहमत हूं कि उत्तर अति-सरलीकृत चीजों का है और एक ऑटो-संपत्ति की सारी शक्ति नहीं दिखा रहा है, हालांकि मैं असहमत हूं कि यह वस्तु-उन्मुख नहीं है। आप खेतों और संपत्तियों के बीच अंतर की जांच करना चाह सकते हैं । फ़ील्ड वर्चुअल नहीं हो सकते, और virtualस्वयं ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग का हिस्सा है।
Gobe

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

164

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


98

मैं आपको उन गुणों का उपयोग करने के लिए कुछ उदाहरण दूंगा, जो गियर्स मोड़ सकते हैं:

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

1
गंदे ट्रैकिंग के बारे में एक प्रश्न: क्या होगा अगर मैं सीधे क्षेत्र को बदल सकता हूं- मुझे नहीं पता कि अगर ऐसा किया जा सकता है, तो मैं कह सकता हूं: "ऑब्जेक्ट को सहेजने की आवश्यकता नहीं है यदि किसी ऑब्जेक्ट का एक भी FIELD नहीं बदला है" इस प्रकार गंदे ट्रैकिंग कोई अंतर नहीं होगा, क्या मुझे कुछ याद आ रहा है?
साइटें

2
@juanpastas: गंदे ट्रैकिंग के संबंध में गुणों का लाभ यह है कि यदि संपत्ति बसने वाला "गंदे" झंडे को सेट करेगा, तो उस परिदृश्य में जहां ध्वज सेट नहीं है कोड को देखने के लिए किसी भी गुण के मूल्यों का निरीक्षण नहीं करना होगा। अगर वे बदल सकते हैं। इसके विपरीत, एक वस्तु के रूप में खेतों उसके गुण को उजागर करता है, तो सभी क्षेत्रों की सामग्री को पिछले मान (जो न केवल तुलना करने के लिए समय लेता है, लेकिन भी मतलब कोड चाहिए के खिलाफ तुलना में किया जाना चाहिए है पिछले मान)।
सुपरकैट

वे एक अच्छे व्यक्ति हैं यह आपको तरीकों (घटनाओं के रूप में) को ट्रिगर करने की अनुमति देता है, या मान सेट या पढ़ने पर लॉगिंग करता है।
कोलबोक्सप

54

प्रॉपर्टीज़ का उपयोग करके, आप किसी इवेंट को बढ़ा सकते हैं, जब प्रॉपर्टी की वैल्यू (aka। PropertyChangedEvent) या वैल्यू बदलने से पहले कैंसलेशन का समर्थन किया जाता है।

खेतों के साथ (प्रत्यक्ष पहुंच) यह संभव नहीं है।

public class Person {
 private string _name;

 public event EventHandler NameChanging;     
 public event EventHandler NameChanged;

 public string Name{
  get
  {
     return _name;
  }
  set
  {
     OnNameChanging();
     _name = value;
     OnNameChanged();
  }
 }

 private void OnNameChanging(){       
     NameChanging?.Invoke(this,EventArgs.Empty);       
 }

 private void OnNameChanged(){
     NameChanged?.Invoke(this,EventArgs.Empty);
 }
}

3
मुझे इसे खोजने में काफी समय लगा। यह एक MVVM है । धन्यवाद ! :)

46

चूंकि उनमें से कई ने तकनीकी पेशेवरों और विपक्षों के साथ समझाया है Propertiesऔर Field, यह वास्तविक समय के उदाहरणों में आने का समय है।

1. गुण आपको केवल-पढ़ने के लिए पहुँच स्तर सेट करने की अनुमति देता है

के मामले पर विचार dataTable.Rows.Countऔर dataTable.Columns[i].Caption। वे वर्ग से आते DataTableहैं और दोनों हमारे लिए सार्वजनिक हैं। उन तक पहुंच-स्तर में अंतर यह है कि हम मूल्य निर्धारित नहीं dataTable.Rows.Countकर सकते हैं, लेकिन हम पढ़ सकते हैं और लिख सकते हैं dataTable.Columns[i].Caption। क्या यह संभव है Field? नहीं!!! यह Propertiesकेवल के साथ किया जा सकता है ।

public class DataTable
{
    public class Rows
    {       
       private string _count;        

       // This Count will be accessable to us but have used only "get" ie, readonly
       public int Count
       {
           get
           {
              return _count;
           }       
       }
    } 

    public class Columns
    {
        private string _caption;        

        // Used both "get" and "set" ie, readable and writable
        public string Caption
        {
           get
           {
              return _caption;
           }
           set
           {
              _caption = value;
           }
       }       
    } 
}

2. संपत्ति संपत्ति में गुण

आपने ButtonVisual Studio में काम किया होगा । इसके गुणों को इस PropertyGridतरह दिखाया गया है Text, Nameआदि। जब हम एक बटन को खींचते हैं और छोड़ते हैं, और जब हम गुणों को क्लिक करते हैं, तो यह स्वचालित रूप से वर्ग Buttonऔर फ़िल्टर ढूंढ लेगा Propertiesऔर दिखाएगा कि PropertyGrid(जहां वे सार्वजनिक हैं तब भी PropertyGridनहीं दिखाएंगे Field)।

public class Button
{
    private string _text;        
    private string _name;
    private string _someProperty;

    public string Text
    {
        get
        {
           return _text;
        }
        set
        {
           _text = value;
        }
   } 

   public string Name
   {
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   } 

   [Browsable(false)]
   public string SomeProperty
   {
        get
        {
           return _someProperty;
        }
        set
        {
           _someProperty= value;
        }
   } 

में PropertyGrid, गुण Nameऔर Textदिखाए जाएंगे, लेकिन नहीं SomeProperty। क्यों??? क्योंकि गुण स्वीकार कर सकते हैं गुण । यह उस मामले में नहीं दिखाई देता है जहां [Browsable(false)]झूठा है।

3. गुण के अंदर बयानों को निष्पादित कर सकते हैं

public class Rows
{       
    private string _count;        


    public int Count
    {
        get
        {
           return CalculateNoOfRows();
        }  
    } 

    public int CalculateNoOfRows()
    {
         // Calculation here and finally set the value to _count
         return _count;
    }
}

4. बाइंडिंग सोर्स में केवल प्रॉपर्टीज का ही इस्तेमाल किया जा सकता है

बाइंडिंग सोर्स हमें कोड की लाइनों की संख्या को कम करने में मदद करता है। Fieldsद्वारा स्वीकार नहीं किया जाता है BindingSource। हमें उसके Propertiesलिए उपयोग करना चाहिए ।

5. डिबगिंग मोड

विचार करें कि हम Fieldएक मान रखने के लिए उपयोग कर रहे हैं । कुछ बिंदु पर हमें डिबग करने और जांचने की ज़रूरत है कि मूल्य उस क्षेत्र के लिए अशक्त हो रहा है या नहीं। ऐसा करना मुश्किल होगा जहां कोड की लाइनों की संख्या 1000 से अधिक हो। ऐसी स्थितियों में हम उपयोग कर सकते हैं Propertyऔर अंदर डिबग मोड सेट कर सकते हैं Property

   public string Name
   {
        // Can set debug mode inside get or set
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   }

ये दिलचस्प तथ्य हैं, लेकिन आप फ़ील्ड्स और प्रॉपर्टीज़ फिलॉसफ़ी के बिंदु को याद कर रहे हैं।
डेविड फेरेंस्की रोगोजान

फिलिपिंस द्वारा यू का क्या मतलब है ? @ दाविद फ़ेरेन्स्की
साराथ अवानुव

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

2
मेरे उत्तर में मेरा पहला वाक्य पढ़ें। मैंने विशेष रूप से बताया है कि मैं यहां फिर से सब कुछ दोहराने नहीं जा रहा हूं। इसका कोई अर्थ नही बन रहा है!!! लोग पहले विवरण को देखेंगे, फिर उदाहरणों को। चिह्नित उत्तर अच्छी तरह से विवरण देता है, लेकिन मैंने कुछ वास्तविक समय के परिदृश्यों और उदाहरणों के साथ जोड़ा जो समझ में आता है। कृपया टिप्पणी करने से पहले पाठक के नज़रिए से ज़रूर सोचें @Dawid Ferenczy
Sarath Avanavu

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

32

प्रसार - उपयोग (जब और क्यों)

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

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


यह एक भयानक जवाब है, वास्तव में मुझे यह समझने में मदद मिली।
स्टीव ब्यूमन

14

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

यदि आप व्यापक खपत (जैसे .NET फ्रेमवर्क, जो लाखों लोगों द्वारा उपयोग किया जाता है) के लिए डिज़ाइन किया गया एक वर्ग पुस्तकालय लिखते हैं, तो यह एक समस्या हो सकती है। हालाँकि, यदि आप एक छोटे कोड बेस (आंतरिक रूप से <= 50 K लाइनों) के अंदर आंतरिक रूप से उपयोग किए जाने वाले वर्ग को लिख रहे हैं, तो यह वास्तव में कोई बड़ी बात नहीं है, क्योंकि कोई भी आपके परिवर्तनों से प्रतिकूल रूप से प्रभावित नहीं होगा। उस मामले में यह वास्तव में सिर्फ व्यक्तिगत पसंद के लिए आता है।


11

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

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

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

गुण मान प्राप्त करने / निर्धारित करने के लिए जो कुछ भी मतलब है उसे संलग्न करके अमूर्तता के स्तर का समर्थन करते हैं।

अधिकांश / सभी मामलों में गुणों का उपयोग करें, लेकिन दुष्प्रभावों से बचने की कोशिश करें।


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

1
गुणों का कभी भी दुष्प्रभाव नहीं होना चाहिए। यहां तक ​​कि डीबगर मान लेता है कि यह उनका सुरक्षित मूल्यांकन कर सकता है।
क्रेग गिदनी

@Strilanc: मैं पूरी तरह से सहमत हूँ, हालांकि, हमेशा ऐसा नहीं होता है। डिबगर के रूप में, फ़नक्वल के साथ कई समस्याएं हैं यदि आप जिस बारे में बात कर रहे हैं वह है।
ब्रायन रासमुसेन

11

पृष्ठभूमि में एक संपत्ति को तरीकों में संकलित किया जाता है। तो एक Nameसंपत्ति में get_Name()और संकलित किया जाता है set_Name(string value)। यदि आप संकलित कोड का अध्ययन करते हैं तो आप इसे देख सकते हैं। इसलिए उनका उपयोग करते समय एक (बहुत) छोटा प्रदर्शन ओवरहेड होता है। आम तौर पर आप हमेशा एक संपत्ति का उपयोग करेंगे यदि आप किसी क्षेत्र को बाहर के लिए उजागर करते हैं, और आप अक्सर इसका उपयोग आंतरिक रूप से करेंगे यदि आपको मूल्य का सत्यापन करने की आवश्यकता है।


7

जब आप चाहते हैं कि आपका निजी चर (क्षेत्र) अन्य वर्गों से आपकी कक्षा के ऑब्जेक्ट के लिए सुलभ हो, तो आपको उन चर के लिए गुण बनाने की आवश्यकता है।

उदाहरण के लिए यदि मेरे पास "आईडी" और "नाम" नाम के चर हैं जो निजी हैं, लेकिन ऐसी स्थिति हो सकती है जहां कक्षा के बाहर पढ़ने / लिखने के संचालन के लिए इस चर की आवश्यकता होती है। उस स्थिति में, संपत्ति मुझे उस वैरिएबल को प्राप्त करने / लिखने में मदद कर सकती है जो संपत्ति के लिए निर्धारित / सेट के आधार पर पढ़ा जा सकता है। एक संपत्ति एक पठनीय / लेखन / पठनीय दोनों हो सकती है।

यहाँ डेमो है

class Employee
{
    // Private Fields for Employee
    private int id;
    private string name;

    //Property for id variable/field
    public int EmployeeId
    {
       get
       {
          return id;
       }
       set
       {
          id = value;
       }
    }

    //Property for name variable/field
    public string EmployeeName
    {
       get
       {
          return name;
       }
       set
       {
          name = value;
       }
   }
}

class MyMain
{
    public static void Main(string [] args)
    {
       Employee aEmployee = new Employee();
       aEmployee.EmployeeId = 101;
       aEmployee.EmployeeName = "Sundaran S";
    }
}

6

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

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

लेकिन इसका एक फायदा यह भी है कि खेतों में संपत्तियां होती हैं, और उनकी क्षमता "रेफ" / "आउट" मापदंडों के रूप में उपयोग की जाती है। मान लीजिए कि आपके पास निम्नलिखित हस्ताक्षर के साथ एक विधि है:

public void TransformPoint(ref double x, ref double y);

और मान लें कि आप इस विधि का उपयोग इस तरह से बनाई गई एक सरणी को बदलने के लिए करना चाहते हैं:

System.Windows.Point[] points = new Point[1000000];
Initialize(points);

यहाँ मुझे लगता है कि इसे करने का सबसे तेज़ तरीका है, क्योंकि X और Y गुण हैं:

for (int i = 0; i < points.Length; i++)
{
    double x = points[i].X;
    double y = points[i].Y;
    TransformPoint(ref x, ref y);
    points[i].X = x;
    points[i].Y = y;
}

और यह बहुत अच्छा होने जा रहा है! जब तक आपके पास माप नहीं हैं जो अन्यथा साबित होते हैं, तो बदबू फेंकने का कोई कारण नहीं है। लेकिन मेरा मानना ​​है कि यह तकनीकी रूप से उतनी तेज होने की गारंटी नहीं है:

internal struct MyPoint
{
    internal double X;
    internal double Y;
}

// ...

MyPoint[] points = new MyPoint[1000000];
Initialize(points);

// ...

for (int i = 0; i < points.Length; i++)
{
    TransformPoint(ref points[i].X, ref points[i].Y);
}

कुछ माप स्वयं करते हुए, खेतों के साथ संस्करण गुणों के साथ संस्करण के रूप में लगभग 61% समय लेता है (.NET 4.6, Windows 7, x64, रिलीज़ मोड, कोई डीबगर संलग्न नहीं)। TransformPointविधि जितनी महंगी होती है, उतनी ही कम स्पष्ट होती है कि अंतर हो जाता है। इसे स्वयं दोहराने के लिए, पहली पंक्ति के साथ टिप्पणी की गई और उसके साथ टिप्पणी नहीं की गई।

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

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


6

यद्यपि फ़ील्ड और गुण एक-दूसरे के समान दिखते हैं, वे 2 पूरी तरह से अलग भाषा तत्व हैं।

  1. फ़ील्ड स्तर पर डेटा संग्रहीत करने के लिए फ़ील्ड्स एकमात्र तंत्र हैं। फ़ील्ड वैचारिक रूप से वर्ग दायरे में होते हैं। यदि आप अपनी कक्षाओं (वस्तुओं) के उदाहरणों के लिए कुछ डेटा संग्रहीत करना चाहते हैं, तो आपको फ़ील्ड का उपयोग करने की आवश्यकता है। और कोई विकल्प नहीं है। गुण किसी भी डेटा को संग्रहीत नहीं कर सकते हैं, भले ही ऐसा लग सकता है कि वे ऐसा करने में सक्षम हैं। नीचे देखें।

  2. दूसरी ओर गुण कभी भी डेटा संग्रहीत नहीं करते हैं। वे केवल तरीकों की जोड़ी हैं (प्राप्त करें और सेट करें) को समान रूप से फ़ील्ड के रूप में कहा जा सकता है और ज्यादातर मामलों में वे खेतों (पढ़ने या लिखने के लिए) का उपयोग करते हैं, जो कुछ भ्रम का स्रोत है। लेकिन क्योंकि संपत्ति के तरीके (कुछ सीमाएं जैसे निश्चित प्रोटोटाइप के साथ) नियमित सी # विधियां हैं जो वे कर सकते हैं जो नियमित तरीके कर सकते हैं। इसका मतलब है कि उनके पास कोड की 1000 लाइनें हो सकती हैं, वे अपवादों को फेंक सकते हैं, अन्य तरीकों को कॉल कर सकते हैं, यहां तक ​​कि आभासी, सार या ओवरराइड भी हो सकते हैं। क्या गुण विशेष बनाता है, यह तथ्य है कि C # संकलक कुछ अतिरिक्त मेटाडेटा को असेंबली में संग्रहीत करता है जिसका उपयोग विशिष्ट गुणों की खोज करने के लिए किया जा सकता है - व्यापक रूप से उपयोग की जाने वाली सुविधा।

संपत्ति के तरीकों को प्राप्त करें और सेट करें निम्नलिखित प्रोटोटाइप हैं।

PROPERTY_TYPE get();

void set(PROPERTY_TYPE value);

तो इसका मतलब है कि एक क्षेत्र और 2 इसी तरीकों को परिभाषित करके गुणों का 'अनुकरण' किया जा सकता है।

class PropertyEmulation
{
    private string MSomeValue;

    public string GetSomeValue()
    {
        return(MSomeValue);
    }

    public void SetSomeValue(string value)
    {
        MSomeValue=value;
    }
}

इस तरह की संपत्ति अनुकरण प्रोग्रामिंग भाषाओं के लिए विशिष्ट है जो गुणों का समर्थन नहीं करते हैं - जैसे मानक C ++। C # में आपको हमेशा अपने खेतों तक पहुंचने के तरीके के रूप में गुणों को प्राथमिकता देना चाहिए।

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

class OneHundredFields
{
        public int Field1;
        public int Field2;
        ...
        public int Field100;
}

OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.

class OneHundredProperties
{
    public int Property1
    {
        get
        {
            return(1000);
        }
        set
        {
            // Empty.
        }
    }

    public int Property2
    {
        get
        {
            return(1000);
        }
        set
        {
            // Empty.
        }
    }

    ...

    public int Property100
    {
        get
        {
            return(1000);
        }
        set
        {
            // Empty.
        }
    }
}

OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).

हालांकि संपत्ति के तरीके कुछ भी कर सकते हैं, ज्यादातर मामलों में वे वस्तुओं के खेतों तक पहुंचने के तरीके के रूप में सेवा करते हैं। यदि आप किसी क्षेत्र को अन्य वर्गों के लिए सुलभ बनाना चाहते हैं तो आप 2 तरीकों से कर सकते हैं।

  1. खेतों को सार्वजनिक बनाना - उचित नहीं है।
  2. गुणों का उपयोग करना।

यहां सार्वजनिक क्षेत्रों का उपयोग करने वाला एक वर्ग है।

class Name
{
    public string FullName;
    public int YearOfBirth;
    public int Age;
}

Name name=new Name();

name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;

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

name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;

कोड मान्य है, सभी असाइनमेंट निष्पादित किए जाएंगे, हालांकि वे अतार्किक हैं। Ageएक नकारात्मक मूल्य है, YearOfBirthभविष्य में दूर है और आयु के अनुरूप नहीं है और FullNameअशक्त है। फ़ील्ड के साथ आप उपयोगकर्ताओं class Nameको ऐसी गलतियाँ करने से नहीं रोक सकते ।

यहां इन समस्याओं को ठीक करने वाले गुणों वाला एक कोड है।

class Name
{
    private string MFullName="";
    private int MYearOfBirth;

    public string FullName
    {
        get
        {
            return(MFullName);
        }
        set
        {
            if (value==null)
            {
                throw(new InvalidOperationException("Error !"));
            }

            MFullName=value;
        }
    }

    public int YearOfBirth
    {
        get
        {
            return(MYearOfBirth);
        }
        set
        {
            if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year)
            {
                throw(new InvalidOperationException("Error !"));
            }

            MYearOfBirth=value;
        }
    }

    public int Age
    {
        get
        {
            return(DateTime.Now.Year-MYearOfBirth);
        }
    }

    public string FullNameInUppercase
    {
        get
        {
            return(MFullName.ToUpper());
        }
    }
}

कक्षा के अद्यतन संस्करण के निम्नलिखित फायदे हैं।

  1. FullNameऔर YearOfBirthअमान्य मानों के लिए जाँच की जाती है।
  2. Ageलेखन योग्य नहीं है। यह YearOfBirthवर्तमान वर्ष से पुकारा जाता है ।
  3. एक नई संपत्ति UPPER CASE में FullNameInUppercaseपरिवर्तित FullNameहो जाती है। यह संपत्ति के उपयोग का एक छोटा सा वंचित उदाहरण है, जहां गुणों को आमतौर पर प्रारूप में फ़ील्ड मानों को प्रस्तुत करने के लिए उपयोग किया जाता है जो उपयोगकर्ता के लिए अधिक उपयुक्त है - उदाहरण के लिए DateTimeप्रारूप के विशिष्ट संख्यात्मक पर वर्तमान स्थान का उपयोग करना ।

इसके अलावा, गुणों को वर्चुअल या ओवरराइड के रूप में परिभाषित किया जा सकता है - केवल इसलिए कि वे नियमित रूप से .NET विधियाँ हैं। नियमित विधियों के लिए ऐसी संपत्ति विधियों के लिए भी यही नियम लागू होता है।

C # इंडेक्सर्स को भी सपोर्ट करता है जो कि प्रॉपर्टी मेथड्स में इंडेक्स पैरामीटर वाले गुण होते हैं। यहाँ उदाहरण है।

class MyList
{
    private string[]                 MBuffer;

    public MyList()
    {
        MBuffer=new string[100];
    }

    public string this[int Index]
    {
        get
        {
            return(MBuffer[Index]);
        }
        set
        {
            MBuffer[Index]=value;
        }
    }
}

MyList   List=new MyList();

List[10]="ABC";
Console.WriteLine(List[10]);

चूंकि C # 3.0 आपको स्वचालित गुणों को परिभाषित करने की अनुमति देता है। यहाँ उदाहरण है।

class AutoProps
{
    public int Value1
    {
        get;
        set;
    }

    public int Value2
    {
        get;
        set;
    }
}

भले ही class AutoPropsकेवल गुण होते हैं (या ऐसा दिखता है), यह 2 मानों को संग्रहीत कर सकता है और इस वर्ग की वस्तुओं का आकार sizeof(Value1)+sizeof(Value2)= 4 + 4 = 8 बाइट्स के बराबर है ।

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

यहाँ संकलित विधानसभा से ILSpy द्वारा उत्पन्न एक कोड है । वर्ग में छिपे हुए क्षेत्र और गुण उत्पन्न होते हैं।

internal class AutoProps
{
    [CompilerGenerated]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int <Value1>k__BackingField;

    [CompilerGenerated]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int <Value2>k__BackingField;

    public int Value1
    {
        [CompilerGenerated]
        get
        {
            return <Value1>k__BackingField;
        }
        [CompilerGenerated]
        set
        {
            <Value1>k__BackingField = value;
        }
    }

    public int Value2
    {
        [CompilerGenerated]
        get
        {
            return <Value2>k__BackingField;
        }
        [CompilerGenerated]
        set
        {
            <Value2>k__BackingField = value;
        }
    }
}

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

तो जैसा कि आप देख सकते हैं, हालांकि गुणों और क्षेत्रों में समान उपयोग सिंटैक्स हैं वे बहुत अलग अवधारणाएं हैं। यहां तक ​​कि अगर आप स्वचालित गुणों या घटनाओं का उपयोग करते हैं - तो छिपे हुए फ़ील्ड संकलक द्वारा उत्पन्न होते हैं जहां वास्तविक डेटा संग्रहीत होते हैं।

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


4

साथ ही, गुण आपको मान सेट करते समय तर्क का उपयोग करने की अनुमति देते हैं।

तो आप कह सकते हैं कि आप केवल एक पूर्णांक फ़ील्ड में मान सेट करना चाहते हैं, यदि मान x से अधिक है, अन्यथा एक अपवाद फेंकें।

वास्तव में उपयोगी सुविधा।


4

यदि आप थ्रेड प्राइमेटिव का उपयोग करने जा रहे हैं तो आप खेतों का उपयोग करने के लिए मजबूर हैं। गुण आपके थ्रेडेड कोड को तोड़ सकते हैं। इसके अलावा, क्या कहा cory सही है।


1
कब से? संपत्ति के भीतर अपने समर्थन क्षेत्र को बंद करें और यह
बराबरी का है

1
गुण विधियां हैं, और आज किसी भी CIL JIT द्वारा इनबिल्ट नहीं हैं। यदि आप इंटरलॉक्ड जैसे थ्रेड प्राइमेटिव का उपयोग करने जा रहे हैं तो आपके पास फ़ील्ड होना चाहिए। अपने स्रोतों की जाँच करें। माना जाता है कि 'लॉकिंग' गलत शब्द है।
जोनाथन सी डिकिन्सन

4

(यह वास्तव में एक टिप्पणी होनी चाहिए, लेकिन मैं एक टिप्पणी पोस्ट नहीं कर सकता, इसलिए कृपया बहाना करें यदि यह पोस्ट के रूप में उपयुक्त नहीं है)।

मैंने एक बार ऐसी जगह पर काम किया था जहाँ अनुशंसित प्रॉपर्टी के बजाय सार्वजनिक क्षेत्रों का उपयोग करने के लिए था जब बराबर संपत्ति का नुकसान सिर्फ एक क्षेत्र तक पहुंच रहा होगा, जैसे:

get { return _afield; }
set { _afield = value; }

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

संपादित करें: मुझे यह जोड़ना चाहिए कि इस स्थान पर सभी कोड आधार एक ही समय में संकलित किए गए थे, इसलिए उन्होंने सोचा हो सकता है कि कक्षाओं के सार्वजनिक इंटरफ़ेस को बदलना (सार्वजनिक क्षेत्र को संपत्ति में बदलकर) कोई समस्या नहीं थी।


C # 3.0 के बाद से , यहां वर्णित पैटर्न को ऑटो-इंप्लीमेंटेड प्रॉपर्टीज़ नामक सुविधा द्वारा आसानी से समर्थित किया गया है ।
डेविड आरआर

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

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

4

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


4

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

  class SomeClass
  {
     int numbera; //Field

     //Property 
    public static int numbera { get; set;}

  }

3

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


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

एपीआई विकास के बारे में, आप समस्याओं के बिना निजी डेटा के लिए खेतों का उपयोग कर सकते हैं । विषम मामलों में भी जहां आप विधानसभा के भीतर डेटा साझा करना चाहते हैं, आप फ़ील्ड को 'आंतरिक' एक्सेस दे सकते हैं।
डैनियल ईयरविकर

3

IMO, गुण सिर्फ "SetXXX ()" "गेटएक्सएक्सएक्स ()" फ़ंक्शन / तरीके / इंटरफेस जोड़े हैं जिन्हें हमने पहले इस्तेमाल किया था, लेकिन वे अधिक संक्षिप्त और सुरुचिपूर्ण हैं।


3

परंपरागत रूप से निजी क्षेत्रों को गेट्टर और सेटर विधियों के माध्यम से निर्धारित किया जाता है। कम कोड के लिए आप इसके बजाय फ़ील्ड सेट करने के लिए गुणों का उपयोग कर सकते हैं।


3

जब आपके पास एक वर्ग है जो "कार" है। गुण रंग, आकार हैं ।।

जहाँ खेतों को वर्ग के दायरे में परिभाषित किया जाता है।


3

विकिपीडिया से - वस्तु-उन्मुख प्रोग्रामिंग :

ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग (OOP) "ऑब्जेक्ट्स" की अवधारणा पर आधारित एक प्रोग्रामिंग प्रतिमान है, जो डेटा संरचनाएं होती हैं , जिनमें फ़ील्ड के रूप में डेटा शामिल होते हैं , जिन्हें अक्सर विशेषताओं के रूप में जाना जाता है; और कोड, प्रक्रियाओं के रूप में, अक्सर विधियों के रूप में जाना जाता है(महत्व दिया)

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


3

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

जब मैं एक क्लासिक मॉडल निजी क्षेत्र / सार्वजनिक आसानी से संपत्तियों का उपयोग करता हूं, तो 10 निजी क्षेत्रों के लिए मुझे १० सार्वजनिक संपत्तियों को लिखना चाहिए! कोड वास्तव में तेजी से बड़ा हो सकता है। मैं निजी सेटर की खोज करता हूं और अब मैं केवल एक निजी सेटर के साथ सार्वजनिक संपत्तियों का उपयोग करता हूं। सेटर पृष्ठभूमि में एक निजी क्षेत्र बनाते हैं।

यही कारण है कि मेरी पुरानी क्लासिक प्रोग्रामिंग शैली थी:

public class MyClass
{
 private int _id;
 public int ID { get { return _id; } }
 public MyClass(int id)
 {
  _id = id;
 }
}

मेरी नई प्रोग्रामिंग शैली:

public class MyClass
{
 public int ID { get; private set; }
 public MyClass(int id)
 {
  ID = id;
 }
}

हाँ मेरा बुरा, क्षमा करें!
टोनी पिनोट 15

3

इसके बारे में सोचो: आपके पास इस कमरे में प्रवेश करने के लिए एक कमरा और एक दरवाजा है। यदि आप यह जांचना चाहते हैं कि आपके कमरे में कौन आ रहा है और सुरक्षित है, तो आपको संपत्तियों का उपयोग करना चाहिए अन्यथा वे किसी भी दरवाजे पर नहीं होंगे और हर कोई आसानी से w / o में किसी भी विनियमन में आ जाएगा।

class Room {
   public string sectionOne;
   public string sectionTwo;
}

Room r = new Room();
r.sectionOne = "enter";

लोग सेक्शन में आ रहे हैं बहुत आसानी से, कोई चेकिंग नहीं थी

class Room 
{
   private string sectionOne;
   private string sectionTwo;

   public string SectionOne 
   {
      get 
      {
        return sectionOne; 
      }
      set 
      { 
        sectionOne = Check(value); 
      }
   }
}

Room r = new Room();
r.SectionOne = "enter";

अब आपने उस व्यक्ति की जाँच की और उसके बारे में जाना कि क्या उसके साथ कुछ बुरा है


3

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

गुण फ़ील्ड के समान हैं, जिसमें वे राज्यों और किसी ऑब्जेक्ट से जुड़े डेटा को परिभाषित करते हैं।

फ़ील्ड के विपरीत एक संपत्ति में एक विशेष वाक्यविन्यास होता है जो यह नियंत्रित करता है कि कोई व्यक्ति डेटा को कैसे पढ़ता है और डेटा लिखता है, इन्हें गेट और सेट ऑपरेटर के रूप में जाना जाता है। सेट तर्क को अक्सर सत्यापन करने के लिए इस्तेमाल किया जा सकता है।


2

गुण विशेष प्रकार के वर्ग के सदस्य होते हैं, गुणों में हम एक पूर्वनिर्धारित सेट या प्राप्त विधि का उपयोग करते हैं। वे एक्सेसर्स का उपयोग करते हैं जिनके माध्यम से हम निजी क्षेत्रों के मूल्यों को पढ़, लिख या बदल सकते हैं।

उदाहरण के लिए, हमें Employeeनाम, आयु और कर्मचारी_आय के लिए निजी क्षेत्रों के साथ एक वर्ग नाम दिया गया है । हम क्लास के बाहर से इन फील्ड्स को एक्सेस नहीं कर सकते, लेकिन हम इन प्राइवेट फील्ड्स को प्रॉपर्टीज के जरिए एक्सेस कर सकते हैं।

हम गुणों का उपयोग क्यों करते हैं?

वर्ग क्षेत्र को सार्वजनिक करना और उसे उजागर करना जोखिम भरा है, क्योंकि आपके पास नियंत्रण नहीं होगा कि क्या असाइन किया गया है और वापस आ गया है।

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

  • आईडी -ve नहीं होना चाहिए।
  • नाम शून्य करने के लिए सेट नहीं किया जा सकता है
  • पास मार्क केवल पढ़ा जाना चाहिए।
  • यदि छात्र का नाम गायब है, तो कोई नाम वापस नहीं होना चाहिए।

इस समस्या को दूर करने के लिए हम गेट एंड सेट विधि का उपयोग करते हैं।

// A simple example
public class student
{
    public int ID;
    public int passmark;
    public string name;
}

public class Program
{
    public static void Main(string[] args)
    {
       student s1 = new student();
       s1.ID = -101; // here ID can't be -ve
       s1.Name = null ; // here Name can't be null
    }
}

अब हम प्राप्त और सेट विधि का एक उदाहरण लेते हैं

public class student
{
    private int _ID;
    private int _passmark;
    private string_name ;
    // for id property
    public void SetID(int ID)
    {
        if(ID<=0)
        {
            throw new exception("student ID should be greater then 0");
        }
        this._ID = ID;
    }
    public int getID()
    {
        return_ID;
    }
}
public class programme
{
    public static void main()
    {
        student s1 = new student ();
        s1.SetID(101);
    }
    // Like this we also can use for Name property
    public void SetName(string Name)
    {
        if(string.IsNullOrEmpty(Name))
        {
            throw new exeception("name can not be null");
        }
        this._Name = Name;
    }
    public string GetName()
    {
        if( string.IsNullOrEmpty(This.Name))
        {
            return "No Name";
        }
        else
        {
            return this._name;
        }
    }
        // Like this we also can use for Passmark property
    public int Getpassmark()
    {
        return this._passmark;
    }
}

2

अतिरिक्त जानकारी: डिफ़ॉल्ट रूप से, एक्सेस और सेट एक्सेसर्स संपत्ति की तरह ही सुलभ हैं। आप एक्सेसरी एक्सेसिबिलिटी को व्यक्तिगत रूप से नियंत्रित कर सकते हैं (प्राप्त करने और सेट करने के लिए) उन पर अधिक प्रतिबंधक एक्सेस संशोधक लागू करके।

उदाहरण:

public string Name
{
    get
    {
        return name;
    }
    protected set
    {
        name = value;
    }
}

यहां अभी भी सार्वजनिक रूप से एक्सेस किया जाता है (जैसा कि संपत्ति सार्वजनिक है), लेकिन सेट संरक्षित है (एक अधिक प्रतिबंधित एक्सेस स्पेसियर)।


2

गुण का उपयोग फ़ील्ड को उजागर करने के लिए किया जाता है। वे एक्सेसर्स (सेट, गेट) का उपयोग करते हैं जिसके माध्यम से निजी क्षेत्रों के मूल्यों को पढ़ा, लिखा या हेरफेर किया जा सकता है।

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

गुणों का उपयोग करके हम किसी फ़ील्ड पर सेट किए गए डेटा के प्रकार पर सत्यापन सेट कर सकते हैं।

उदाहरण के लिए, हमारे पास निजी पूर्णांक फ़ील्ड आयु है, जिस पर हमें सकारात्मक मूल्यों की अनुमति देनी चाहिए क्योंकि आयु नकारात्मक नहीं हो सकती है।

हम इसे दो तरीकों से कर सकते हैं गेटर और सेटर का उपयोग करके और संपत्ति का उपयोग करके।

 Using Getter and Setter

    // field
    private int _age;

    // setter
    public void set(int age){
      if (age <=0)
       throw new Exception();

      this._age = age;
    }

    // getter
    public int get (){
      return this._age;
    }

 Now using property we can do the same thing. In the value is a key word

    private int _age;

    public int Age{
    get{
        return this._age;
    }

    set{
       if (value <= 0)
         throw new Exception()
       }
    }

यदि हम लॉजिक प्राप्त नहीं करते हैं और एक्सेसर्स सेट करते हैं तो हम ऑटो कार्यान्वित की गई संपत्ति का उपयोग कर सकते हैं।

जब यू सी-ऑटो-कार्यान्वित संपत्ति संकलन एक निजी, अनाम क्षेत्र बनाता है जिसे केवल एक्सेस और सेट एक्सेसर्स के माध्यम से एक्सेस किया जा सकता है।

public int Age{get;set;}

सार गुण एक अमूर्त वर्ग में एक अमूर्त संपत्ति हो सकती है, जिसे व्युत्पन्न वर्ग में लागू किया जाना चाहिए

public abstract class Person
   {
      public abstract string Name
      {
         get;
         set;
      }
      public abstract int Age
      {
         get;
         set;
      }
   }

// overriden something like this
// Declare a Name property of type string:
  public override string Name
  {
     get
     {
        return name;
     }
     set
     {
        name = value;
     }
  }

हम निजी रूप से एक संपत्ति निर्धारित कर सकते हैं। इसमें हम निजी रूप से ऑटो संपत्ति सेट कर सकते हैं (वर्ग के साथ सेट)

public int MyProperty
{
    get; private set;
}

आप इस कोड के साथ एक ही हासिल कर सकते हैं। इसमें प्रॉपर्टी सेट सुविधा उपलब्ध नहीं है क्योंकि हमें सीधे फील्ड में वैल्यू सेट करनी है।

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}

2

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

इसी गुण है जो आप को परिभाषित, करने की अनुमति के साथ उन चर के सभी को सुरक्षित रखें सेट और मिल accessors और मान्यता की तरह बातें करते हैं जब आप डेटा के उन टुकड़ों से छेड़छाड़ कर रहे हैं।

लेकिन मैथ क्लास (सिस्टम नेमस्पेस) जैसे अन्य मामलों में , कुछ स्थिर गुण हैं जो वर्ग में निर्मित होते हैं। जिनमें से एक गणित निरंतर पीआई है

जैसे। Math.PI

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

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