2009-03-06 10 views
19

मैं निम्नलिखित वर्ग है:सी # में संपत्ति Accessor "रीड ओनली"

class SampleClass 
{ 
    private ArrayList mMyList; 

    SampleClass() 
    { 
     // Initialize mMyList 
    } 

    public ArrayList MyList 
    { 
     get { return mMyList;} 
    } 
} 

मैं उन mMyList है, जिसके कारण मैं संपर्क में प्राप्त करने में सक्षम होना चाहता हूँ एक संपत्ति के माध्यम से "मिल" लेकिन मैं नहीं वे ऑब्जेक्ट में किए गए परिवर्तन चाहते हैं (यानी MyList.Add (नई कक्षा());) मेरी कक्षा में वापस जाने के लिए।

मुझे लगता है कि मैं ऑब्जेक्ट की एक प्रति वापस कर सकता हूं लेकिन यह धीमा हो सकता है और मैं ऐसे तरीके की तलाश कर रहा हूं जो उपयोगकर्ता को सूचित करने में संकलित समय त्रुटि प्रदान करेगी कि उन्हें संशोधित करने में सक्षम होने की उम्मीद नहीं करनी चाहिए संपत्ति से मूल्य वापस कर दिया।

क्या यह संभव है?

+0

संबंधित प्रश्न: http://stackoverflow.com/प्रश्न/681287/कैसे-टू-मेक-ए-रेफरेंस-टाइप-प्रॉपर्टी-रीडोनली –

+2

क्या सूची है: ReadOnlyCollection '.NET 4.5 में इनमें से कोई भी परिवर्तन? http://www.infoq.com/news/2011/10/ReadOnly-WInRT/ –

उत्तर

25

एक ऐरेलिस्ट के साथ आप काफी सीमित हैं क्योंकि बीसीएल में कोई भी गैर-सामान्य संग्रह वर्ग नहीं है। त्वरित और गंदा समाधान एक प्रकार का IENumerable वापस करना है।

public IEnumerable MyList 
    { 
     get { return mMyList;} 
    } 

यह वास्तव में ArrayList के लिए कास्टिंग से किसी को रोकने नहीं होगा, लेकिन यह डिफ़ॉल्ट या तो

करके संपादन अनुमति नहीं दी जाएगी आप ArrayList.ReadOnly को फोन करके एक प्रभावी रूप से केवल पढ़ने के लिए सूची लौट सकते हैं। हालांकि यह रिटर्न प्रकार एक ऐरेलिस्ट है इसलिए उपयोगकर्ता अभी भी संकलित करने में सक्षम होगा। लेकिन यह एक रनटाइम त्रुटि उत्पन्न करेगा।

1

आपको वापसी मूल्य को केवल पढ़ने के संग्रह में लपेटना चाहिए।

19

सूची के चारों ओर केवल पढ़ने के लिए रैपर बनाने और वापस करने के लिए ArrayList.ReadOnly() विधि का उपयोग करें। यह सूची की प्रतिलिपि नहीं करेगा, लेकिन इसके आस-पास केवल पढ़ने-योग्य रैपर बनाएं। संकलन-समय की जांच करने के लिए, आप संभवतः केवल-पढ़ने वाले रैपर को IENumerable के रूप में @ जेरेड सुझावों के रूप में वापस करना चाहते हैं।

public IEnumerable MyList 
{ 
    get { return ArrayList.ReadOnly(mMyList); } 
} 

एक संग्रह है कि केवल पढ़ने के लिए है बस एक आवरण कि संग्रह को संशोधित करने से बचाता है के साथ एक संग्रह। यदि अंतर्निहित संग्रह में परिवर्तन किए जाते हैं, तो केवल पढ़ने के लिए संग्रह उन परिवर्तनों को दर्शाता है।

यह विधि एक ओ (1) ऑपरेशन है।

Reference

+2

मैं इस समाधान के खिलाफ हूं क्योंकि यह एक रनटाइम त्रुटि में संकलन समय त्रुटि होना चाहिए। – JaredPar

+0

-1, ओपी: "मैं एक ऐसे तरीके की तलाश में हूं जो एक ** संकलन-समय ** त्रुटि प्रदान करेगा" –

+0

एक ReadOnlyCollection की प्रतिलिपि के बिना - जिसे उसने यह भी कहा कि वह टालना चाहता था - मैं पढ़ने- केवल पढ़ने के लिए नाटक करने पर। दोनों करना वास्तव में शायद बेहतर है। – tvanfosson

-3

बस संपत्ति सील (या VB.NET में NotInheritable) और केवल पढ़ने के लिए, के रूप में इस तरह करते हैं:

public sealed readonly ArrayList MyList 
    { 
     get { return mMyList;} 
    } 

भी मत भूलना समर्थन क्षेत्र के रूप में केवल पढ़ने के लिए बनाने के लिए :

private readonly ArrayList mMyList; 

लेकिन एमएमलिस्ट के मूल्य को आरंभ करने के लिए, आपको इसे केवल कन्स्ट्रक्टर में प्रारंभ करना होगा, एक इस उदाहरण में:

public SampleClass() 
{ 
    // Initialize mMyList 
    mMyList = new ArrayList(); 
} 
10

सिर्फ जेरेडपार के उत्तर पर विस्तार करने के लिए। जैसा कि उन्होंने कहा, वास्तविक बैकिंग फ़ील्ड को वापस करना पूरी तरह से सुरक्षित नहीं है, क्योंकि उपयोगकर्ता अभी भी IEnumerable को ArrayList पर गतिशील रूप से डालने में सक्षम है।

मैं कुछ इस तरह लिखने यकीन है कि मूल सूची में कोई संशोधन किया जाता है मानेंगे:

public IEnumerable MyList 
{ 
    get 
    { 
     foreach (object o in mMyList) 
      yield return o; 
    } 
} 

तो फिर, मैं probabily भी एक सामान्य सूची (IEnumerable<T>) पूरी तरह से सुरक्षित टाइप किए जाने का प्रयोग करेंगे।

+0

* यह * सही है - इच्छा है कि मैं दो बार वोट दे सकता हूं। लूप के बाद 'उपज तोड़ने 'के साथ कोई समस्या नहीं है? – Jay

+0

@Jay: लूप के बाद स्पष्ट 'उपज ब्रेक' की कोई आवश्यकता नहीं है। विधि का अंत 'गणनाकर्ता' के अंत का तात्पर्य है (और 'MoveNext' सही ढंग से' झूठा 'वापस आ जाएगा)। –

+0

इस समाधान के साथ उपयोगकर्ता ArrayList की कार्यक्षमता खो देता है जैसे तेज़ यादृच्छिक अभिगम और तेज़ गणना? –

4

ReadOnlyCollection का उपयोग करें।

return new ReadOnlyCollection<object>(mMyList)

आप ReadOnlyCollection एक फ़ील्ड भी बना सकते हैं, और यह अंतर्निहित सूची में स्वचालित रूप से परिवर्तनों को प्रतिबिंबित करेगा। यह सबसे कुशल समाधान है।

यदि आप जानते हैं कि एमएमलिस्ट में केवल एक प्रकार का ऑब्जेक्ट होता है (उदाहरण के लिए, इसमें डेटटाइम्स के अलावा कुछ भी नहीं है), आप अतिरिक्त प्रकार की सुरक्षा के लिए ReadOnlyCollection<DateTime> (या किसी अन्य प्रकार) को वापस कर सकते हैं। आप सी # 3 उपयोग कर रहे हैं, तो आप बस

return new ReadOnlyCollection<DateTime>(mMyList.OfType<DateTime>().ToArray())

बहरहाल, यह स्वचालित रूप से अंतर्निहित सूची के साथ अपडेट नहीं होगा लिख ​​सकते हैं, और यह भी कम कुशल है (यह पूरी सूची की प्रतिलिपि बनाएगा) । सबसे अच्छा विकल्प बनाने के लिए mMyList है एक सामान्य List<T> (जैसे, एक List<DateTime>)

0

नेट v2.0 से उपलब्ध

public ArrayList MyList { get; private set; } 
+0

आप अभी भी मौजूदा सूची में जोड़ें का उपयोग करने में सक्षम होंगे। –

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