2009-09-11 16 views
11

बारे में कुछ भी जादू इस कोड को हो रही है ...वहाँ ReadOnlyCollection

var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 }); 
b[2] = 3; 

मैं दूसरी पंक्ति में एक संकलन त्रुटि मिलती है। मुझे ReadOnlyCollection<T> लागू होने के बाद रनटाइम त्रुटि की उम्मीद होगी IList<T> और this[T]IList<T> इंटरफ़ेस में एक सेटटर है।

मैंने ReadOnlyCollection की कार्यक्षमता को दोहराने की कोशिश की है, लेकिन this[T] से सेटर को हटाने का संकलन त्रुटि है।

उत्तर

16

indexer स्पष्ट साथ लागू किया गया है इंटरफेस कार्यान्वयन, ताकि आप केवल इसे उपयोग करने में सक्षम हो जाएगा अगर आप कार्य करें:

IList<int> b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 }); 
b[2] = 3; 

या

var b = new ReadOnlyCollection<int>(new[] { 2, 4, 2, 2 }); 
((IList<int>)b)[2] = 3; 
बेशक

, यह तो निष्पादन समय असफल होगा ...

यह पूरी तरह से जानबूझकर और उपयोगी है - इसका मतलब है कि यह एक ReadOnlyCollection, कार्यक्षमता के असमर्थित बिट्स उपलब्ध नहीं हैं जब संकलक जानता है आप के लिए, निष्पादन समय विफलता से दूर करने में मदद करने के लिए।

हालांकि यह एक दिलचस्प और अपेक्षाकृत असामान्य कदम है, प्रभावी रूप से संपत्ति/सूचकांक का आधा हिस्सा स्पष्ट रूप से कार्यान्वित करता है, और एक आधा स्पष्ट रूप से।

मेरे पिछले विचारों के विपरीत, मेरा मानना ​​है कि ReadOnlyCollection<T>वास्तव में स्पष्ट रूप से पूरे इंडेक्सर को लागू करता है, लेकिन भी एक सार्वजनिक केवल पढ़ने के लिए इंडेक्सर प्रदान करता है।

public T Item[int index] { get; } 

T IList<T>.Item[int index] { get; set; } 

आप डाली हैं:

T IList<T>.this[int index] 
{ 
    // Delegate interface implementation to "normal" implementation 
    get { return this[index]; } 
    set { throw new NotSupportedException("Collection is read-only."); } 
} 

public T this[int index] 
{ 
    get { return ...; } 
} 
+0

ठीक है, लेकिन मैं स्पष्ट कार्यान्वयन का उपयोग कर ReadOnlyCollection की कार्यक्षमता दोहराता हूं। मैं नहीं देखता कि आप इंटरफ़ेस से विधि या संपत्ति को कैसे हटा सकते हैं। –

+0

@EsbenP: आप इंटरफ़ेस से कोई विधि नहीं हटा सकते हैं ... लेकिन आप इसे केवल तभी उपलब्ध कर सकते हैं जब संदर्भ का स्थिर प्रकार इंटरफ़ेस को लागू करने वाले वर्ग के बजाय इंटरफ़ेस है। –

+0

ठीक है, अगर मैं दो indexers, उन्हें IList को लागू करने की एक स्पष्ट रूप से यह काम करता है टी IList .इस [पूर्णांक सूचकांक] {{ वापसी स्रोत [सूचकांक] प्राप्त होता है; } सेट { नया नोट लागू नहीं किया गया अपवाद(); } } सार्वजनिक टी यह [पूर्णांक सूचकांक] {{ वापसी स्रोत [सूचकांक] प्राप्त होता है; } } –

2

यह आईएलआईस्ट लागू करता है। यह स्पष्ट रूप से, जो इसे गैर-सार्वजनिक बनाता है, और आपको इसके क्रियान्वयन तक पहुंचने के लिए इंटरफ़ेस में डालना होगा, और यह एक नया [...] सूचकांक लागू करता है, जिसका उपयोग इसके बजाय किया जाता है, जो केवल एक प्राप्तकर्ता है।

यदि आप संग्रह को IList में डालते हैं, तो आपका कोड संकलित होगा, लेकिन इसके बजाए रनटाइम में विफल हो जाएगा।

दुर्भाग्य से मैं कैसे सी # में यह करने के लिए, सी # में एक इंडेक्सर लेखन this कीवर्ड का इस्तेमाल किया जाता के बाद से पता नहीं है, और आप नहीं लिख सकते हैं इस:

T IList<T>.this[int index] { get; set; } 
+0

@Lasse: अपनी खुद की कक्षा में इंडेक्सर को लागू करने के लिए आपको this कीवर्ड का उपयोग आप पाएंगे कि लिख सकते हैं - उचित कार्यान्वयन के साथ। समस्या यह है कि जहां तक ​​मैं कह सकता हूं, आप एक आधे स्पष्ट रूप से और आधा अंतर्निहित रूप से लागू नहीं कर सकते हैं। –

+0

यदि आप इसे लिख सकते हैं, तो आपको सेट अप लिखने की ज़रूरत नहीं है, और आप एक अपवाद फेंकने के साथ सेटर लिखते हैं, और फिर आप इसे [..] सूचकांक को केवल गेटर के साथ लागू करते हैं। –

1

कोई जादू नहीं है, ReadOnlyCollection बस अपने आप इंडेक्सर और इंडेक्सर कि IList<T> इंटरफ़ेस लागू करता है के लिए अलग अलग कार्यान्वयन है: दूसरे शब्दों में, यह कुछ इस तरह है

((IList<int>)b)[2] = 3; 

संपादित करें:: के लिए अपनी सूची, आप संकलन त्रुटि के बजाय एक रनटाइम त्रुटि मिल जाएगा

public T this[int index] { get { ... } } 

T IList<T>.this[int index] { get { ... } set { ... } } 
+0

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

+0

संकलन त्रुटि संदेश क्या है? – thecoop

+0

@EsbenP: इसे कक्षा में कार्यान्वित करने के लिए सिंटैक्स दस्तावेज़ीकरण में दिखाए गए हस्ताक्षर के समान नहीं है। उपरोक्त संपादन देखें। – Guffa