2010-02-23 13 views
6

में ऑब्जेक्ट्स बनाना बस कोड के बारे में उत्सुक था।लूप सी #

for (int i=0; i<9; i++) 
{ 
    ClassA objectA = new ClassA(); 
} 

या

ClassA objectA; 
for (int i=0; i<9; i++) 
{ 
    objectA = new ClassA(); 
} 

कोई आइडिया दोनों कोड के लिए कोई अंतर है? मेरे ज्ञान से दोनों अलग-अलग उदाहरण बनाएंगे, इसलिए हर बार उदाहरण चल रहे हैं .. कोई विचार?

उत्तर

25

Scoping एक तरफ (अर्थात चर लूप के बाहर मौजूद है या नहीं) वहाँ आमतौर पर कोई अंतर नहीं है, के बाद से नेट चर वैसे भी शुरू विधि के पर वास्तव में कर रहे (IL) में सभी। हालांकि, एक अपवाद है: यदि आप चर (एक अज्ञात विधि/लैम्ब्डा में) को कैप्चर करते हैं, तो यह अलग-अलग व्यवहार करता है - कैप्चर सी # घोषणा के संबंध में बनाया गया है। तो:

List<Action> actions = new List<Action>(); 
ClassA objectA; 
for (int i=0;i<9;i++) 
{ 
    objectA= new ClassA(); 
    actions.Add(delegate { Console.WriteLine(objectA.GetHashCode()); });   
} 
foreach(Action action in actions) action(); 

और: (पहले प्रिंट ही पता आधारित हैश कोड 9 बार

List<Action> actions = new List<Action>(); 
for (int i=0;i<9;i++) 
{ 
    ClassA objectA= new ClassA(); 
    actions.Add(delegate { Console.WriteLine(objectA.GetHashCode()); });   
} 
foreach(Action action in actions) action(); 

अलग बातें करेंगे, दूसरा प्रिंट 9 अलग पता आधारित हैश -कोड्स, यह दर्शाता है कि दूसरे लूप में हमने 9 अलग-अलग वैरिएबल को एक चर के बजाय कैप्चर किया है)।

दोनों मामलों में 9 ClassA ऑब्जेक्ट बनाए गए हैं - बस हम पहले मामले में उनमें से 8 को और नहीं देख सकते हैं।

+4

+1 क्योंकि यह वास्तव में दिलचस्प है। –

+1

सामान्य मार्क के रूप में, आप उम्मीद से परे पहुंचते हैं। लैम्ब्डा करते समय दायरा कभी-कभी क्रैक करने के लिए एक कठिन अखरोट है।मुझे यकीन है कि हम सभी को ऊपर बताए गए स्कोपिंग समस्या से जला दिया गया है। मुझे पता है मेरे पास है। चीयर्स! – TheSoftwareJedi

0

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

उदाहरण के लिए,

for (int i = 0; i < 9; i++) 
{ 
    ClassA objectA = new ClassA(); 
    someFunc(() => objectA); 
} 

हो सकता था की तुलना में

ClassA objectA; 
for (int i = 0; i < 9; i++) 
{ 
    objectA = new ClassA(); 
    someFunc(() => objectA); 
} 
+0

आप यहां विशेष रूप से बंद क्यों करते हैं? 'someFunc (objectA) 'प्रत्येक ऑब्जेक्ट का संदर्भ सहेज सकता है, उदाहरण के लिए, यदि' someFunc' संग्रह का 'जोड़ें' फ़ंक्शन है। –

+0

'someFunc (objectA) 'लूप के माध्यम से प्रत्येक पुनरावृत्ति के एक अलग ऑब्जेक्ट का संदर्भ पारित करेगा; 'someFunc (() => objectA) 'क्लासए' घोषित होने के आधार पर या तो एक ही या अलग संदर्भ पारित करेगा। – Gabe

13

फर्क सिर्फ इतना है अलग दिखाई परिणाम है कि दूसरे उदाहरण में, पिछले बनाई उदाहरण अभी भी एक्सेस किया जा सकेगा पाश के बाद

0

दोनों के बीच का अंतर यह है कि लूप पूर्ण होने के बाद, कक्षा से कक्षा का उदाहरण ई अंतिम पुनरावृत्ति (i = 8) शेष कार्य के लिए उपलब्ध होगा, जबकि पहले संस्करण में, यह नहीं होगा।

0

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

2

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

हालांकि, के मामले में:

for (int i=0;i<9;i++) 
{ 
    ClassA objectA = new ClassA(); 
} 

objectA पाश के दायरे से बाहर मौजूद नहीं है, और वस्तुओं आपके द्वारा बनाई गई के सभी अंत में कचरा कलेक्टर द्वारा हटा दिया जाएगा। यह लूप के बाहर objectA को संदर्भित करने के लिए एक वाक्यविन्यास त्रुटि होगी।

इसके विपरीत, के मामले में:

ClassA objectA; 
for (int i=0;i<9;i++) 
{ 
    objectA= new ClassA(); 
} 

objectA लूप के बाहर एक वैध पहचानकर्ता, और ClassA बनाया पाश पूर्ण होने के बाद ही रहेगा के अंतिम उदाहरण है।

1

पहले स्निपेट में, ऑब्जेक्ट लूप के बाहर पहुंच योग्य नहीं होगा। इस प्रकार, यदि आपने लिखा:

for (int i=0;i<9;i++) 
{ 
    ClassA objectA = new ClassA(); 
} 
// This will not compile. 
objectA.DoSomething(); 

आपको संकलन त्रुटि प्राप्त होगी। हालांकि, अगर आप के रूप में कोड लिखा है:

ClassA objectA; 
for (int i=0;i<9;i++) 
{ 
    objectA= new ClassA(); 
} 
// This will compile. 
objectA.DoSomething(); 

दूसरा कोड स्निपेट संकलन होगा (यह मानते हुए ClassA एक विधि DoSomething नामक())।

0

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

प्रासंगिक अंतर एक क्रिबली द्वारा इंगित किया गया है, क्योंकि आप पहले उदाहरण पर स्कोप (जो भी {और} के बीच है) के बाहर चर (जो ऑब्जेक्ट संदर्भ है) का उपयोग नहीं कर सकते हैं। चूंकि दूसरे पर आप लूप के बाहर चर घोषित करते हैं, फिर भी आप चर का उपयोग कर सकते हैं।

के रूप में मार्क Gravell कहा, आईएल उत्पन्न दोनों के लिए समान है, इसलिए वहाँ पाश के लिए प्रदर्शन, स्मृति कब्जे, आदि, के मामले में कोई अंतर नहीं होना चाहिए। [1]


1: चूंकि दूसरे उदाहरण पर निश्चित रूप से अंतिम चर के संदर्भ को बनाए रखा है, कचरा कलेक्टर अपनी जगह को मुक्त नहीं कर पाएगा। तो, लूप समाप्त होने के बाद, सूक्ष्म मतभेद होंगे।

2

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

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