2010-02-27 7 views
19

कैसे सी #, या उस बात के लिए अन्य भाषाओं, स्मृति आवंटन (और स्मृति de-आवंटन) इन दो स्थितियों के बीच संभाल करता है:सी # वर्ग उदाहरण

1.) पर एक विधि एक स्थिर वर्ग का आह्वान किया जाता है।

public Program { 
    Foo foo = Loader.load(); 
} 

public static Loader { 
    public static Foo load() { 
     return new Foo(); 
    } 
} 

2.) एक उदाहरण पर एक विधि लागू की जाती है, जो तब दायरे से बाहर हो जाती है।

public Program { 
    Foo foo = new Loader().load(); 
} 

public Loader { 
    public Foo load() { 
     return new Foo(); 
    } 
} 

मुझे लगता है स्थिर वर्ग भरी हुई है, और स्मृति में रहता है,; जबकि कक्षा का उदाहरण सी # के अवकाश पर कचरा संग्रह के लिए सफल होता है। क्या इन दो प्रतिमानों के लिए कोई पेशेवर या विपक्ष है? क्या कभी ऐसा समय होता है जब आपके पास ऐसी कक्षा होती है जिसे कभी भी तत्काल होने की आवश्यकता नहीं होती है (यानी कुछ प्रकार के संसाधन लोडर या फैक्ट्री), लेकिन कचरा संग्रह का लाभ उठाने के लिए आप दूसरी पद्धति का उपयोग करते हैं?

मेरे प्रश्न का महत्वपूर्ण हिस्सा यह है कि पहले परिस्थिति में, कुछ परिस्थितियों में अवधारणात्मक रूप से सही होने पर, अनावश्यक रूप से स्मृति को पकड़ने से पीड़ित हो सकता है।

+3

दूसरा उदाहरण मेरे लिए गलत लगता है। एक स्थिर विधि को कॉल करने के लिए कक्षा वर्ग के साथ उपसर्ग करना आवश्यक है। जैसे 'लोडर। लोड()' और ** नहीं ** 'नया लोडर() लोड()' – shahkalpesh

+0

आप सही हैं, शाह - आपको एक स्थिर विधि को कॉल करने के लिए एक उदाहरण की आवश्यकता नहीं है। यह थोड़े बिंदु है :) –

+0

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

उत्तर

8

आपका दूसरे उदाहरण काम नहीं करता है, तो चलो असली विकल्पों की तलाश करते हैं:

1.) एक स्थिर वर्ग पर एक विधि शुरू हो जाती है।

public Program { 
    Foo foo = Loader.Load(); 
} 

public static Loader { 
    public static Foo Load() { 
     return new Foo(); 
    } 
} 

2.) एक गैर स्थैतिक कक्षा में एक स्थिर विधि शुरू हो जाती है।

public Program { 
    Foo foo = Loader.Load(); 
} 

public Loader { 
    public static Foo Load() { 
     return new Foo(); 
    } 
} 

3.) एक उदाहरण विधि एक उदाहरण

public Program { 
    Foo foo = new Loader().Load(); 
} 

public Loader { 
    public Foo Load() { 
     return new Foo(); 
    } 
} 

दो पहले ही कर रहे हैं पर शुरू हो जाती है। एक स्थैतिक विधि को कॉल करना वही है चाहे कक्षा स्थिर है या नहीं।

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

एक आवृत्ति विधि को कॉल करना एक स्थिर विधि से थोड़ा अलग है। क्लास इंस्टेंस के संदर्भ में भेजा गया है, कि आप this कीवर्ड के माध्यम से पहुंच सकते हैं। इससे इस मामले में थोड़ा अंतर आता है क्योंकि ऑब्जेक्ट में पहुंचने के लिए कोई वास्तविक डेटा नहीं है।

+0

क्या किसी सी # प्रोग्राम का मेमोरी पदचिह्न बदलता है जब ऑब्जेक्ट का एक उदाहरण कचरा इकट्ठा होता है (उदाहरण फ़ील्ड डेटा के अलावा, जाहिर है), क्या कभी भी टाइप की गई जानकारी की कोई अनलोडिंग होती है? इसे बोलने के लिए, सी # कभी भी किसी भी अनुकूलन को निष्पादित करेगा जैसे "ओह, इन कक्षाओं में से कोई भी वर्तमान में उदाहरण नहीं है, मुझे अब उनकी आवश्यकता नहीं है, मैं प्रोग्राम से कच्चे प्रकार के डेटा को अनलोड कर दूंगा और खुद को कुछ यादगार सहेज दूंगा "? – jtb

+0

@jtb: नहीं, मेरे ज्ञान के लिए .NET एक असेंबली को अनलोड नहीं करेगा जिसे एक बार लोड किया गया था। – Guffa

+0

@jtb जीसी केवल तभी आपकी कक्षा द्वारा ली गई मेमोरी होगी यदि उसके पास कोई संदर्भ/हैंडल इत्यादि नहीं है और केवल तभी जब ओएस मेमोरी संसाधन दुर्लभ हैं। –

1

एक स्थिर विधि, फ़ील्ड, संपत्ति, या घटना कक्षा में कॉल करने योग्य है, भले ही कक्षा का कोई उदाहरण नहीं बनाया गया हो। यह प्रकार के स्कोप:

http://msdn.microsoft.com/en-us/library/79b3xss3(VS.80).aspx

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

+0

हाँ, श्रीमान, मेरा उदाहरण मेरे प्रश्न को स्पष्ट करने के लिए खराब लिखे जाने से पीड़ित है। मुझे नहीं पता कि यह उचित एसओ शिष्टाचार है, क्योंकि आप सही हैं, लेकिन मुझे वास्तव में पूछे जाने वाले प्रश्न पूछने के लिए मुझे अपने प्रश्न को फिर से भरना होगा। – jtb

+0

यह देखते हुए कि एक स्थिर सदस्य प्रकार के लिए scoped है, मुझे नहीं लगता कि स्मृति उपयोग बस बदलने जा रहा है क्योंकि आप इसे उस प्रकार के उदाहरण के भीतर कहते हैं। –

1

दूसरा रूप अस्थायी Loader ऑब्जेक्ट बनाता है (जो बहुत सस्ता है)। आपको हमेशा लोडर क्लास लोड करना होगा, इससे कोई फर्क नहीं पड़ता कि आप किस दृष्टिकोण को चुनते हैं।

यहां हासिल करने के लिए बहुत कम प्रदर्शन (स्मृति बचत) है। स्थानीय वर्रों के तरीकों के बाहर आवश्यक 'राज्य' नहीं होने पर आप सामान्य रूप से एक स्थिर वर्ग में एक स्थिर सदस्य के लिए चयन करेंगे।

+0

@ हेंक: दूसरा उदाहरण सी # में संकलित नहीं होगा। सही? – shahkalpesh

+0

@ शाह यह संकलित करेगा। नोट 2 उदाहरण एक स्थिर विधि नहीं बुला रहा है! यह एक सामान्य सार्वजनिक विधि को एक उदाहरण के भीतर बुला रहा है जिसे तब कचरा इकट्ठा किया जाता है क्योंकि इसे कभी भी फिर से नहीं किया जाता है। –

+0

हाँ, लोग उलझन में हैं क्योंकि मेरी मूल पोस्ट में दूसरे उदाहरण में विधि स्थिर थी, मैंने इसे संपादित किया। – jtb

0

मैं इस के लिए किसी भी स्रोत नहीं मिल सकता है, लेकिन प्रोग्रामिंग, जब आप एक वर्ग (गैर स्थिर) refernce की मेरी जानकारी से, यह संरचना स्मृति

सिर्फ एक विधि कॉल करने के एक वर्ग का एक उदाहरण बनाना में लोड किया जाता है , बहुत सारी प्रोसेसिंग पावर बर्बाद कर देगा (उदाहरण बनाने के कारण, इसे मेमोरी असाइन करना, और कचरा इकट्ठा करना)।

परिभाषा को रखने के बजाय, और फिर इसके शीर्ष पर, एक उदाहरण। क्यों न केवल परिभाषा (स्थैतिक) रखें।

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

+0

जब एक स्थैतिक वर्ग का पहले संदर्भ दिया जाता है, तो मेरी समझ यह है कि सी # स्थिर प्रारंभिक चलाता है, स्थिर फ़ील्ड को मेमोरी में लोड करता है, और टाइप रन (क्लास स्ट्रक्चर) को मेमोरी में लोड करता है, इसे प्रोग्राम रनटाइम की अवधि के लिए वहां रखता है। जब किसी वर्ग का एक उदाहरण बनाया जाता है, तो निर्माता को संसाधित किया जाता है, उदाहरण फ़ील्ड के लिए मेमोरी आवंटित की जाती है और टाइप डेटा स्मृति में लोड होता है (यदि यह पहले से नहीं है)। हालांकि, जब एक वर्ग का एक उदाहरण गुंजाइश छोड़ देता है, तो अंततः डेटा ईथर को दिया जाता है, लेकिन क्या टाइप डेटा कभी जारी किया जाता है? – jtb

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