2011-03-11 21 views
7

मैं निम्नलिखित सार्वजनिक संपत्ति है जो एक Arraylist को उजागर करता है:गुण - मूल्य या संदर्भ के द्वारा?

public ArrayList SpillageRiskDescriptions 
     { 
      get 
      { 
       return _SpillageRiskDescriptions; 
      } 
      set 
      { 
       _SpillageRiskDescriptions = value; 
      } 
     } 

कहीं और मैं

SpillageRiskDescriptions.Add("VENTILATE AREA"); 
SpillageRiskDescriptions.Add("DO NOT ALLOW SPILLAGE TO ENTER MAINS"); 

फोन कर रहा हूँ इन (संपत्ति के माध्यम से) निजी ArrayList _SpillageRiskDescriptions के तत्वों को जोड़ने हो रहे हैं जबकि मैं एक समस्या का कारण बनने की उम्मीद करता। इसलिए क्या मैं यह सोचने में सही हूं कि गुण संदर्भ मूल चर में लौटते हैं और इसे मान से गुजरते हैं? क्या ऐसा इसलिए है क्योंकि ArrayList एक संदर्भ प्रकार है? int (उदाहरण के लिए?)

उत्तर

9

तकनीकी रूप से यह हमेशा मूल्य से होता है, लेकिन आपको समझना होगा कि क्या हो रहा है। चूंकि यह संदर्भ प्रकार है, इसलिए आप एक संदर्भ वापस भेज रहे हैं (लेकिन मूल्य से)।

आशा है कि यह समझ में आता है। आप हमेशा परिणाम के आधार पर परिणाम पास करते हैं, लेकिन यदि प्रकार एक संदर्भ है तो आप संदर्भ द्वारा वापस संदर्भ पारित कर रहे हैं, जिसका अर्थ है कि आप ऑब्जेक्ट को बदल सकते हैं, लेकिन यह किस ऑब्जेक्ट को संदर्भित नहीं करता है।

+2

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

+0

उत्कृष्ट - यह सही समझ में आता है –

1

के साथ ऐसा ही होगा, इसके साथ कोई संबंध नहीं है कि यह एक संपत्ति है; यह संपत्ति का डेटा प्रकार है। इस मामले में, आप ArrayList का उपयोग कर रहे हैं जो संदर्भ द्वारा पारित एक वर्ग है। अगर संपत्ति int के रूप में टाइप की गई थी तो इसे मूल्य से पारित किया जाएगा।

2

सी # संदर्भ द्वारा वस्तुओं को वापस करता है।

केवल चीजें हैं जो मूल्य द्वारा दिया नहीं कर रहे हैं कर रहे हैं:

आदिम प्रकार के।
संरचना प्रकार।
Enums।

+0

सार में सच है, हालांकि तकनीकी रूप से यह मूल्य के आधार पर ऑब्जेक्ट संदर्भ वापस भेजता है। –

+0

इसके अलावा सी ++ पॉइंटर्स मूल्य से वापस पास किए जाते हैं, लेकिन यह संदर्भ द्वारा परिभाषा है। ऑब्जेक्ट का पता ऑब्जेक्ट के बजाए पास किया जाता है। –

0

एक संपत्ति वास्तव में दो तरीकों की एक जोड़ी है - एक सेटटर और गेटर। वे बैकिंग फ़ील्ड (या जिसे स्रोत/गंतव्य के रूप में उपयोग किया जाता है) के मान को पास करते हैं। इसलिए, संदर्भ प्रकारों के लिए संदर्भ पारित किया गया है, और मूल्य प्रकारों के लिए मान पास हो गया है।

// this is how the getter method looks like 
public ArrayList get_SpillageRiskDescriptions() 
{ 
    return _SpillageRiskDescriptions; 
} 

// this is how the setter method looks like 
public void set_SpillageRiskDescriptions(ArrayList value) 
{ 
    _SpillageRiskDescriptions = value; 
} 

ध्यान दें कि अपनी संपत्ति में एक ArrayList उदाहरण बताए द्वारा आप मूल रूप से ArrayList उदाहरण की जगह समर्थन फ़ील्ड द्वारा इंगित किए।

अपने विशेष सवालों के जवाब देने के लिए:

इसलिए मैं सोच में सही कर कि गुण मूल चर करने के लिए एक संदर्भ लौट हूँ और मूल्य द्वारा इसे पारित नहीं?

नहीं, गेटर का उपयोग करके आपको _SpillageRiskDescriptions फ़ील्ड का संदर्भ नहीं मिलता है। आपको क्षेत्र के मूल्य मिलते हैं जो एक (गतिशील रूप से आवंटित) ArrayList उदाहरण का संदर्भ है।

क्या यह ArrayList एक संदर्भ प्रकार है?

हाँ, ArrayList एक संदर्भ प्रकार है और इस प्रकार आप विशेष ArrayList उदाहरण के संदर्भ में प्राप्त करते हैं।

क्या int (उदाहरण के लिए) के साथ ऐसा ही होगा?)

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

0

इसमें संपत्ति के साथ कुछ भी नहीं है।

इस मामले में, आप मूल्य के अनुसार सरणी सूची का संदर्भ पारित कर रहे हैं।

यदि आप करते हैं जैसे

 void AddSomethingToArrayList(ArrayList spillageRiskDescriptions){ 
      spillageRiskDescriptions.Add("Something"); 
     } 

कुछ तो सरणी सूची के संदर्भ संशोधित किया जाएगा।

आप की तरह

 void ReassignArrayList(ArrayList spillageRiskDescriptions){ 
      spillageRiskDescriptions = new ArrayList(); 
      spillageRiskDescriptions.Add("Something"); 
     } 

कुछ करने के लिए थे, तो सरणी सूची में मूल संदर्भ में सब बदल नहीं किया जाएगा।

लेकिन आप इस तरह के रूप में संदर्भ द्वारा पारित करने के लिए संदर्भ थे:

 void ReassignArrayListByRef(ref ArrayList spillageRiskDescriptions){ 
      spillageRiskDescriptions = new ArrayList(); 
      spillageRiskDescriptions.Add("Something"); 
     } 

तो अपनी संपत्ति एक आइटम के साथ एक नई सरणी सूची के साथ समाप्त होगा।

7

अन्य उत्तर सही ढंग से अपनी प्राथमिक सवाल का जवाब है: कि संदर्भ प्रकार के संपत्ति के मूल्य एक संदर्भ संदर्भ प्रकार का एक उदाहरण है।

बड़ा सवाल यह है कि "अब आप इसके बारे में क्या करते हैं?" संभवतः आप कोड चाहते हैं जो प्राप्त कर सकते हैं को बदलने में सक्षम होने के लिए सूची प्राप्त करें।

यहां कई विकल्प हैं।

सबसे पहले, कोई फर्क नहीं पड़ता कि आप क्या करते हैं, मैं अनुशंसा करता हूं कि आप अभी ArrayList का उपयोग करना बंद करें और चीजों की एक सूची संग्रहीत करने के लिए एक अधिक आधुनिक, सुरक्षित प्रकार का उपयोग शुरू करें। List<string> तुरंत दिमाग में आता है।

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

तीसरा, हमारे पास "छोटी" संपत्ति के लिए एक अधिक कॉम्पैक्ट वाक्यविन्यास है।आप कह सकते हैं

public List<string> SpillageListDescriptions { get; private set; } 

और संकलक आपके लिए बैकिंग फ़ील्ड उत्पन्न करेगा।

ध्यान दें कि List<string> अभी भी उत्परिवर्तन की अनुमति देता है।

सभी ग्राहक परवाह करता है के बारे में एक समय में सूची एक बात से अधिक पुनरावृति करने में सक्षम किया जा रहा है, तो आप ऐसा कर सकते हैं:

private List<string> descriptions = whatever; 
public IEnumerable<string> SpillageListDescriptions 
{ 
    get 
    { 
     if (descriptions == null) yield break; 
     foreach(var description in descriptions) 
      yield return description; 
    } 
} 

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

या आप कर सकता है:

private List<string> descriptions = whatever; 
public IList<string> SpillageListDescriptions 
{ 
    get 
    { 
     return new ReadOnlyCollection<string>(descriptions); 
    } 
} 

और अब फोन करने वाले सूची अगर वे इसे संशोधित करने का प्रयास है कि एक अपवाद फेंक होगा की केवल पढ़ने के लिए दृश्य है।

+0

आपकी प्रतिक्रिया के लिए बहुत धन्यवाद हालांकि इनमें से अधिकतर (लघु संपत्ति सिंटैक्स और सार्वजनिक गेटर के साथ निजी सेटटर) केवल ढांचे के बाद के संस्करणों में उपलब्ध हैं - मैं .NET2 का उपयोग कर रहा हूं। मैं वास्तव में इसका दौरा करने का पूरा कारण यह है कि मैं ArrayList को सूची में परिवर्तित कर सकता हूं। हालांकि यह पता लगाने के लिए अच्छा है कि मैं क्या कर रहा हूं वह सही है। –

+0

उन्होंने जो एकमात्र समाधान उल्लेख किया है वह .Net 2 में उपलब्ध नहीं है, वह ऑटो-प्रॉपर्टीज है, जिसे हाथ से 2 में छोटा रूप से कार्यान्वित किया जा सकता है। आपको 'var' को' string' से प्रतिस्थापित करने की भी आवश्यकता होगी। – Brian

संबंधित मुद्दे