2010-06-14 10 views
8

क्या मुझे लगता है कि एल्गोरिदमिक प्रोग्रामिंग पर ठीक है, अगर यह सही शब्द है? मैं 1 9 80 के दशक में टर्बो पास्कल और 8086 असेंबली भाषा के साथ एक शौक के रूप में खेलता था। लेकिन तब से केवल बहुत छोटी परियोजनाएं और मैंने वास्तव में 20 वर्षों के वर्षों में कोई प्रोग्रामिंग नहीं किया है। तो मैं एक डूबने वाले तैराक की तरह समझने के लिए संघर्ष कर रहा हूं।क्या होता है जब आप किसी ऑब्जेक्ट का उदाहरण बनाते हैं जिसमें C# में कोई स्थिति नहीं है?

तो शायद यह एक बहुत ही निष्कपट सवाल यह है कि या मैं बस सब पर कोई मतलब नहीं बना रहा हूं, लेकिन कहते हैं कि मैं इस तरह तरह का एक उद्देश्य है:

class Something : IDoer 
{ 
    void Do(ISomethingElse x) 
    { 
     x.DoWhatEverYouWant(42); 
    } 
} 

और फिर मैं

var Thing1 = new Something(); 
var Thing2 = new Something(); 

Thing1.Do(blah); 
Thing2.Do(blah); 
करना

Thing1 = Thing2 करता है? क्या "नया कुछ()" कुछ भी बनाता है? या यह स्थिर वर्ग होने से बहुत अलग नहीं है, सिवाय इसके कि मैं इसे चारों ओर पास कर सकता हूं और इसे स्वैप कर सकता हूं।

क्या थिंग 1 (ब्लाह) और थिंग 2 दोनों के लिए स्मृति में एक ही स्थान पर "Do" प्रक्रिया है (ब्लाह) वस्तुओं? मेरा मतलब यह है कि इसे निष्पादित करते समय, क्या इसका मतलब है कि दो कुछ हैं। प्रक्रियाएं या सिर्फ एक?

उत्तर

7

स्मृति में सबसे निश्चित रूप से दो अलग-अलग वस्तुएं हैं। प्रत्येक वस्तु ढेर पर 8 बाइट्स का उपभोग करेगी (कम से कम 32-बिट सिस्टम पर); 4 सिंकब्लॉक के लिए और टाइप हैंडल के लिए 4 (जिसमें विधि तालिका शामिल है)। सिस्टम-परिभाषित राज्य डेटा के अलावा आपके मामले में कोई अन्य उपयोगकर्ता परिभाषित राज्य डेटा नहीं है।

Something.Do विधि के लिए कोड का एक उदाहरण है। टाइप ऑब्जेक्ट पॉइंटर जो प्रत्येक ऑब्जेक्ट धारण करता है वह है कि सीएलआर कक्षा के लिए विभिन्न विधियों को कैसे ढूंढता है। तो स्मृति में दो अलग-अलग वस्तुएं हैं, फिर भी वे दोनों एक ही कोड निष्पादित करते हैं। चूंकि Something.Do को एक इंस्टेंस विधि के रूप में घोषित किया गया था, तो इसमें this पॉइंटर आंतरिक रूप से पास हो जाएगा ताकि कोड सही उदाहरण सदस्यों को संशोधित कर सके कि किस ऑब्जेक्ट विधि का आह्वान कर रहा था। आपके मामले में Something कक्षा में कोई उदाहरण सदस्य नहीं है (और इस प्रकार कोई उपयोगकर्ता परिभाषित राज्य नहीं है) और इसलिए यह काफी अप्रासंगिक है, लेकिन फिर भी ऐसा होता है।

5

नहीं वे समान नहीं हैं। वे Something वर्ग के दो अलग-अलग उदाहरण हैं। वे समान रूप से तत्काल होने लगते हैं, यह सब कुछ है।

+0

लेकिन इस बात की स्मृति में वास्तव में क्या है? संदर्भ के पीछे, एक सूचक है, जो स्मृति में वस्तु की स्थिति को इंगित करता है। तो यह कहां इंगित करता है? –

+0

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

+0

मुझे लगता है कि ब्रायन गिदोन ने इसका उत्तर दिया। –

0

Thing1! = Thing2
ये स्मृति में दो अलग-अलग वस्तुएं हैं।

द विधि विधि दोनों ऑब्जेक्ट्स के लिए एक ही स्थान पर है। विधि की दो अलग-अलग प्रतियों को स्टोर करने की कोई आवश्यकता नहीं है।

4

आप 2 "खाली" ऑब्जेक्ट्स बनाएंगे, प्रत्येक ऑब्जेक्ट के लिए ढेर पर एक छोटा आवंटन होगा।

लेकिन "डू" विधि हमेशा एक ही स्थान पर होती है, जिसका राज्य की अनुपस्थिति से कोई लेना-देना नहीं है। कोड किसी वर्ग/वस्तु में 'इन' संग्रहित नहीं होता है। Do() से संबंधित कोड का केवल 1 टुकड़ा है और इसमें 'छुपा' पैरामीटर this है जो उस चीज़ के उदाहरण को इंगित करता है जिसे इसे कॉल किया गया था।

12

वे दो अलग-अलग वस्तुएं हैं; वे सिर्फ राज्य नहीं है।

var obj1 = new object(); 
var obj2 = new object(); 

Console.WriteLine(object.ReferenceEquals(obj1, obj2)); 

यह उत्पादन False करेंगे:

इस कोड पर विचार करें।

सिर्फ इसलिए कि किसी ऑब्जेक्ट का कोई राज्य नहीं है इसका मतलब यह नहीं है कि इसे किसी अन्य ऑब्जेक्ट की तरह आवंटित नहीं किया जाता है। यह बहुत कम जगह लेता है (बस object की तरह)।

आपके प्रश्न के अंतिम भाग के जवाब में: केवल एक Do विधि है। विधि प्रति उदाहरण नहीं बल्कि प्रति वर्ग के लिए संग्रहीत हैं। यदि आप इसके बारे में सोचते हैं, तो प्रति उदाहरण उन्हें स्टोर करना बेहद अपर्याप्त होगा। Something ऑब्जेक्ट पर Do पर प्रत्येक विधि कॉल वास्तव में निर्देशों का एक ही सेट है; विभिन्न वस्तुओं से कॉल के बीच जो कुछ अलग है वह अंतर्निहित वस्तु की स्थिति है (यदि Something वर्ग के साथ कोई भी राज्य शुरू होना था, तो यह है)।

इसका क्या अर्थ है कि कक्षा वस्तुओं पर उदाहरण विधियां वास्तव में वैचारिक तरीके से वैचारिक तरीके से समान हैं।

आप इस बारे में सोच सकते हैं जैसे सभी इंस्टेंस-लेवल विधियों का गुप्त रूप से अनुवाद किया गया था (मैं यह नहीं कह रहा हूं कि यह सख्ती से सच है, बस आप इस तरह से सोच सकते हैं और यह समझ में आता है):

// appears to be instance-specific, so you might think 
// it would be stored for every instance 
public void Do() { 
    Do(this); 
} 

// is clearly static, so it is much clearer it only needs 
// to be stored in one place 
private static Do(Something instance) { 
    // do whatever Do does 
} 

दिलचस्प ओर ध्यान दें: ऊपर काल्पनिक "अनुवाद" काफी बताते हैं कि कैसे विस्तार तरीके काम: वे स्थिर तरीके हैं, लेकिन this कीवर्ड के साथ अपने पहले पैरामीटर योग्यता से, वे अचानक उदाहरण के तरीकों की तरह देखो ।

+0

उस पर एक एरिक लिपर्ट प्रतिक्रिया देखना चाहेंगे। मुझे संदेह है कि कक्षा को सील नहीं किया गया है और यह एक इंटरफेस से विरासत में आता है कि कुछ प्रकार के आभासी विधि सूचक के लिए कुछ स्मृति होगी ... मुद्दा यह है कि उनका अंतिम प्रश्न वास्तव में दिलचस्प है लेकिन डरावनी जानकारियों की आवश्यकता है। –

+0

कृपया मेरी टिप्पणी डेविड एम –

+0

पर देखें ... और यहां पूछे गए एक से अलग प्रश्न है। –

0

प्रत्येक संदर्भ प्रकार (थिंग 1, थिंग 2) मुख्य स्मृति में एक अलग भौतिक पते की ओर इशारा कर रहा है, क्योंकि उन्हें अलग से तत्काल किया गया है। स्मृति में इंगित चीज वस्तु द्वारा उपयोग किए जाने वाले बाइट्स है, चाहे उसके पास राज्य हो या नहीं (यह हमेशा एक राज्य है, लेकिन क्या यह घोषित/प्रारंभिक स्थिति है)।

यदि आपने किसी संदर्भ प्रकार को अन्य संदर्भ प्रकार (थिंग 2 = थिंग 1;) पर असाइन किया है तो यह दो अलग-अलग संदर्भ प्रकारों द्वारा उपयोग की जाने वाली स्मृति का एक ही हिस्सा होगा, और कोई नया क्षण नहीं होगा।

1

संकल्पनात्मक रूप से, थिंग 1 और थिंग 2 अलग-अलग वस्तुएं हैं, लेकिन केवल एक ही चीज़ है। प्रक्रिया।

नेट रनटाइम आपके द्वारा बनाई गई प्रत्येक ऑब्जेक्ट में थोड़ी-थोड़ी मेमोरी आवंटित करता है - एक टुकड़ा Thing1 और दूसरे को Thing2 में। स्मृति के इस खंड का उद्देश्य वस्तु (1) वस्तु की स्थिति को संग्रहित करना है और (2) वस्तु से संबंधित किसी भी प्रक्रिया का पता है। मुझे पता है कि आपके पास कोई राज्य नहीं है, लेकिन रनटाइम परवाह नहीं है - यह अभी भी स्मृति के दो अलग-अलग हिस्सों में दो अलग-अलग संदर्भ रखता है।

अब, आपकी "डू" विधि थिंग 1 और थिंग 2 दोनों के लिए समान है, रनटाइम केवल स्मृति में प्रक्रिया का एक संस्करण रखता है।

वह आवंटित स्मृति थिंग 1 में विधि विधि का पता शामिल है। जब आप Thing1 पर Do Method का आह्वान करते हैं, तो यह Thing1 के लिए अपनी Do विधि का पता देखता है और विधि चलाता है। दूसरी बात, थिंग 2 के साथ भी यही बात होती है। हालांकि ऑब्जेक्ट्स अलग हैं, वही डू विधि को थिंग 1 और थिंग 2 दोनों के लिए बुलाया जाता है।

यह क्या उबलता है कि थिंग 1 और थिंग 2 अलग हैं, जिसमें "थिंग 1" और "थिंग 2" नाम स्मृति के विभिन्न क्षेत्रों को संदर्भित करते हैं। इस स्मृति की सामग्री दोनों मामलों में समान है - एक ऐसा पता जो "Do" विधि को इंगित करता है।

वैसे, यह सिद्धांत है, वैसे भी।हुड के तहत, कुछ प्रकार का अनुकूलन हो सकता है (यदि आप रुचि रखते हैं तो http://www.wrox.com/WileyCDA/Section/CLR-Method-Call-Internals.id-291453.html देखें), लेकिन अधिकांश व्यावहारिक उद्देश्यों के लिए, मैंने जो कहा है, वैसे ही चीजें काम करती हैं।

0

नए कन्स्ट्रक्टर() के बारे में सोचने का एक अच्छा तरीका यह है कि आप वास्तव में केवल अपनी कक्षा के अंदर विधि को बुला रहे हैं, इसलिए एकमात्र ज़िम्मेदारी आपको उस वस्तु का एक नया उदाहरण प्रस्तुत करना है जो आपकी कक्षा से पकी हुई कुकी है।

तो अब आप क्रम स्थितियों के सभी प्रकार से निपटने में चारों ओर चल रहे एक ही कक्षा के कई उदाहरण हो सकते हैं: डी

जहाँ तक CLR के रूप में, आप देखेंगे कि प्रत्येक की ओर इशारा शामिल स्मृति पर वास्तव में 2 अलग उदाहरणों हो रही है यह, यह किसी भी अन्य ओओपी भाषा के समान है लेकिन हमें वास्तव में पॉइंटर्स के साथ बातचीत करने की ज़रूरत नहीं है, उनका अनुवाद गैर संदर्भ प्रकार के समान होता है, इसलिए हमें उनके बारे में चिंता करने की ज़रूरत नहीं है!

(वहाँ सी # में संकेत अगर आप अपने [असुरक्षित] कीवर्ड बाहर कोड़ा करना चाहते हैं!)

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

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