2016-09-07 6 views
5

मैंने fact पर ठोकर खाई कि सूचकांक this[int index] { get; } structs की सूची के लिए structs की एक सरणी के लिए अलग-अलग काम करता है। अर्थात्, T[] के मामले में सूचकांक सरणी के भीतर तत्व का संदर्भ देता है जबकि List<T> के मामले में सूचकांक तत्व की एक प्रति देता है।ऐरे इंडेक्सर हस्ताक्षर ऑब्जेक्ट देता है - क्या यह बॉक्स करता है?

यह एक बहुत बड़ा अर्थपूर्ण और प्रदर्शन अंतर है, और मुझे खुशी है कि T[] हमें List<T> की प्रदर्शन सीमा के आसपास काम करने की अनुमति देता है।

हालांकि, मैं वास्तविक कार्यान्वयन से परेशान हूं। .net संदर्भ स्रोतों में Array के लिए code इस प्रकार लिखा है:

Object IList.this[int index] { 
    get { return GetValue(index); } 
    set { SetValue(value, index); } 
} 

कहाँ GetValue के रूप में परिभाषित किया गया है इस प्रकार है:

public unsafe Object GetValue(int index) 
{ 
    if (Rank != 1) 
     throw new ArgumentException(Environment.GetResourceString("Arg_Need1DArray")); 
    Contract.EndContractBlock(); 
    TypedReference elemref = new TypedReference(); 
    InternalGetReference(&elemref, 1, &index); 
    return TypedReference.InternalToObject(&elemref); 
} 

इंडेक्सर की वापसी प्रकार Object है, जिसका अर्थ है कि मुक्केबाजी को होगा।

तो मेरा सवाल यह है कि, क्या मैं निश्चित हो सकता हूं कि कोई बॉक्सिंग तब नहीं होगी जब मैं T[] के तत्व तक पहुंचूं जहां T एक संरचना है?

मुझे लगता है कि संकलक और/या सीएलआर विशेष रूप से ऐरे का इलाज करते हैं, और वास्तव में सूचकांक के हस्ताक्षर से परेशान नहीं हैं। क्या ये सही है? क्या इस बारे में कहीं अधिक चर्चा है?

+0

'IList.SomeMethod' एक [अंतर्निहित intefrace] है (http://stackoverflow.com/q/143405/1997232) कार्यान्वयन। यह कहने का एक तरीका है * "यह विधि मौजूद है यदि ऑब्जेक्ट को 'IList'' * के रूप में वर्गीकृत किया गया है। इसका उपयोग केवल तभी किया जाएगा जब आप विशेष रूप से अनुरोध करते हैं, उदा। इंडेक्सर के मामले में ((IList) someArray) [x] '। सरणी इंडेक्सर को सीधे एक्सेस करना (उदा। 'SomeArray [x] ') एक और बात है, आपको किसी भी विधि के लिए स्रोत नहीं मिलेगा क्योंकि कोई भी नहीं है। – Sinatr

उत्तर

9

अर्थात्, एक टी [] के मामले में इंडेक्सर सरणी

नहीं वास्तव में भीतर तत्व के लिए संदर्भ देता है कि। यह और भी है कि सरणी के लिए एक सूचकांक नहीं है - इसके बजाय तत्व-पहुंच अभिव्यक्ति तत्व तत्व के बजाय सरणी पहुंच का प्रतिनिधित्व करती है (क्रमशः सी # 5 spec के खंड 7.6.6.1 और 7.6.6.2)।

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

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

तो मेरी सवाल है, मुझे लगता है कि कोई मुक्केबाजी जब मैं एक T[] जहां T एक struct है का एक तत्व का उपयोग हो जाएगा कुछ हो सकता है?

आप इसे एक T[] के रूप में, सुनिश्चित करें कि प्रवेश कर रहे हैं। आपके द्वारा देखी गई इंडेक्सर केवल तभी उपयोग की जाती है जब आप सरणी को IList के रूप में देख रहे हों। तो यदि आप इसका उपयोग करते हैं:

IList array = new int[2]; 
object x = array[0]; 

तो हाँ, यह मान बॉक्स करेगा ...लेकिन आप तो

int[] array = new int[2]; 
int x = array[0]; 

बारे में अगर वह ऐसा नहीं करेगा और यह कि इंडेक्सर कोड या बिल्कुल GetValue विधि तक पहुँचने नहीं किया जाएगा।

+0

इसे देखने का एक और तरीका: 'System.Array' सभी सरणी के मूल प्रकार की तरह है। इस आधार प्रकार में 'IList.this [int अनुक्रमणिका] 'का कार्यान्वयन मौजूद है इसलिए सरणी' System.Collections.IList' को लागू करेगी, नियमित तत्व पहुंच के लिए नहीं। –

+0

ग्रेट, धन्यवाद। एक अनुवर्ती प्रश्न - क्या Array.cs में कुछ भी है जिसे निष्पादित किया जाता है जब मैं सरणी [अनुक्रमणिका] कहता हूं? या यह सब सीएलआर द्वारा सीधे लागू किया गया है? – bright

+1

@bright: सीएलआर में सभी, जहां तक ​​मुझे पता है। विशेष रूप से सरणी पहुंच के लिए आईएल है, हालांकि मुझे ओप नामों को बंद नहीं किया जा सकता है। –

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