2012-04-19 21 views
11

पर कॉलिंग मैं सी ++/सीएलआई से सी # में कुछ कोड बदलने के बीच में हूं। वस्तुओं में से एक सी ++/सीएलआई संस्करण में एक विनाशक है। कुछ अन्य सी ++/सीएलआई कोड उपयोग के बाद इस ऑब्जेक्ट पर "हटाएं" कहते हैं।कॉलिंग सी ++/सीएलआई सी # ऑब्जेक्ट

इस ऑब्जेक्ट के सी # संस्करण में मुझे किस विधि को लागू करने की आवश्यकता है, इसलिए उन "हटाएं" एक ही काम कर रहे हैं (IDISposable.Dispose, फ़ाइनलाइज़र, या कुछ और जो मुझे याद आ रही है)?

उत्तर

16

मैं कहूंगा कि IDisposable इंटरफेस आप अगर आप संसाधनों की नियतात्मक निपटान की जरूरत है क्या ढूंढते हैं। यह आमतौर पर अप्रबंधित संसाधनों के मामले में होता है, जैसे अप्रबंधित हैंडल जिन्हें बंद, स्ट्रीम या डेटाबेस कनेक्शन होना आवश्यक है।

C++/CLI में, यदि आप एक प्रबंधित प्रकार (ref class और की तरह) की घोषणा, IDisposable नाशक सिंटैक्स का उपयोग कार्यान्वित किया जाता है, और Dispose()delete कीवर्ड का उपयोग करके कहा जाता है। आप (^ ऑपरेटर या gcnew का उपयोग किए बिना) एक कामयाब प्रकार स्थानीय स्तर पर इस तरह के एक वस्तु की घोषणा करते हैं, तो C++/CLI भी आपके लिए अपने आप Dispose() कॉल जब वस्तु क्षेत्र से बाहर चला जाता है। इस तरह, सी ++/सीएलआई सी # से अधिक सुविधाजनक है।

सी # का उपयोग करते समय आप ऑब्जेक्ट पर delete पर कॉल करने में सक्षम नहीं होंगे, आपको इसके बजाय मैन्युअल रूप से Dispose() पर कॉल करने की आवश्यकता होगी। IDisposable ऑब्जेक्ट्स का निपटान करने का एक और तरीका using ब्लॉक है।

finalizer (नाशक वाक्य रचना का उपयोग करके सी # में लागू) के बाद से यह निर्धारित करने योग्य नहीं है जब यह कहा जाएगा, एक सी ++ नाशक के रूप में ही नहीं है। फाइनलज़र के साथ ऑब्जेक्ट्स मूल रूप से कतारबद्ध होते हैं जब तक कि फाइनलाइज़र थ्रेड अपने फाइनलाइज़र को कॉल करने का फैसला नहीं करता है, इसलिए प्रभावी रूप से आप इसे कभी भी नहीं जानते हैं जब इसे कहा जाता है।

अप्रबंधित संसाधनों से निपटने के लिए सबसे अच्छा तरीका शायद दोनों का संयोजन है। यहाँ की सिफारिश की दृष्टिकोण के लिए देखें:
http://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.100).aspx

ध्यान दें, तथापि, कि जब IDisposable का उपयोग कर, भले ही आप अप्रबंधित संसाधनों की निर्धारणात्मक नष्ट कर सकें, वस्तुओं अभी भी कचरा कलेक्टर द्वारा एकत्र होने के लिए (गैर निर्धारणात्मक) की जरूरत है में कामयाब रहे।

मैं सिर्फ एक लेख C++/CLI और सी # के बीच इस बात का मतभेद समझा पाया। आपको यह दिलचस्प लगेगा:
http://weblogs.thinktecture.com/cnagel/2006/04/ccli-finalize-and-dispose.html

+1

सी ++/सीएलआई स्टैक अर्थशास्त्र के साथ जेनरेट किए गए आईएल पर अतिरिक्त ध्यान दें या केवल स्थानीय लोगों को न केवल कक्षा के सदस्यों पर काम करें। सी # में डुप्लिकेट करने का कोई आसान तरीका नहीं है। –

+0

यह नहीं पता था (सी ++/सीएलआई का उपयोग अक्सर नहीं)। जानकारी के लिए धन्यवाद :) – Botz3000

+0

मैंने अभी जवाब को दोबारा पढ़ा है और मुझे कुछ स्पष्टीकरण की आवश्यकता है: यदि मेरी कक्षा को सी # (और आईडीआईस्पोज़बल लागू करता है) में परिभाषित किया गया है, तो क्या मैं इसका उपयोग करते समय इसे "हटाएं" पर कॉल कर पाऊंगा एक और सी ++/सीएलआई कक्षा से? धन्यवाद! –

0

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

यह अन्य वस्तुओं है कि किसी भी स्पष्ट सफाई की आवश्यकता नहीं है को नष्ट करने है, तो मैं सिर्फ नाशक छोड़ देते हैं और जीसी इसे संभाल करते हैं।

1

सी # एक ही उपकरण प्रदान नहीं करता है, लेकिन यह आप के लिए पैटर्न प्रदान करता है: अपने dtor, एक धारा बंद हो रहा है संकेत अनलिंक करने, या उचित रूप से राज्यों की स्थापना तो मुझे लगता है IDisposable इंटरफ़ेस एक अच्छा फिट है:

// C# 
void Dispose() 
{ 
    _stream.Close(); 
    _ptr = null; 
    _running = false; 
} 

// with 

obj.Dispose(); 

आप वास्तव में स्मृति खुला रखने के लिए जी सी के लिए मजबूर नहीं कर सकते। जीसी को जानने में मदद करने के तरीके हैं कि अधिक जानकारी के लिए http://msdn.microsoft.com/en-us/library/ee787088.aspx पढ़ें।

ध्यान रखें कि IDisposable का उपयोग करके आप Dispose() विधि को उचित रूप से कॉल करने की अपेक्षा करते हैं। तो प्रत्येक delete के स्थान पर, आप Dispose() का उपयोग करना चाहेंगे। फाइनेंजर का सुरक्षित हिस्सा यह है कि जब जीसी वास्तव में इसे मुक्त कर रहा है, तो इसे बुलाया जाएगा। हालांकि, आप खुद को फाइनलाइज़र नहीं कह सकते हैं (इसलिए अगर डिलीट/निपटान पर समय महत्वपूर्ण है, तो यह सही समाधान नहीं है।)

+1

वह सी ++/सीएलआई से परिवर्तित हो रहा है, जो पहले से ही एक निर्धारित भाषा है जो गैर-निर्धारक कचरा संग्रह के साथ है। लेकिन .NET एक निर्धारिक निपटान पैटर्न जोड़ता है, जिसमें सी ++/सीएलआई में उत्कृष्ट भाषा समर्थन है, और वह पूछ रहा है कि उसे सी # में अनुवाद कैसे करें। सी # में निपटान के लिए भाषा समर्थन भी है, लेकिन लगभग सुरुचिपूर्ण नहीं है। –

+0

यह इंगित करने के लिए धन्यवाद कि - हाँ, इसमें एक पैटर्न है और मैं उसे उपयुक्त मामलों के साथ उस पैटर्न पर इंगित कर रहा था। मैं यह जवाब देने के लिए अपना उत्तर ठीक कर दूंगा कि वह सी ++/सीएलआई – payo

4

सी ++/सीएलआई और सी # के बीच एक शब्दावली मेल नहीं है। सी ++/सीएलआई विनाशक (~ फू) IDISposable है।() विधि कार्यान्वयन का प्रयास करें। एक सी ++/सीएलआई कक्षा स्पष्ट रूप से IDisposable लागू नहीं करता है, यह केवल एक विनाशक की उपस्थिति से स्वचालित है।

सी ++/सीएलआई फाइनलाइज़र (! फू) सी # विनाशक है।

तो सी ++/सीएलआई हटाएं ऑपरेटर निपटान() विधि को कॉल करने के बराबर है। सी ++/सीएलआई में स्टैक सेमेन्टिक्स से सावधान रहें, बिना टोपी के संदर्भ प्रकार के स्थानीय चर द्वारा ट्रिगर किया गया। कंपाइलर स्कोप ब्लॉक के अंत में निपटान() को छुपा कॉल उत्पन्न करता है। जो कीवर्ड का उपयोग कर C# के बराबर है। स्रोत कोड से देखना मुश्किल है, इसलिए ildasm.exe

+1

से आ रहा है बस एक स्पष्टीकरण: हालांकि सी # दस्तावेज "विनाशकों" के बारे में बात करता है, सी # वास्तव में विनाशक नहीं है। सी # में विनाशक नोटेशन का उपयोग एक फाइनलाइज़र बनाता है। और सी ++/सीएलआई स्टैक अर्थशास्त्र 'ब्लॉक' का उपयोग कर सी # 'से कहीं ज्यादा शक्तिशाली हैं। –

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