2012-10-12 25 views
9

यहां मुझे एक मुश्किल स्थिति है, मुझे लगता है। मुझे किसी ऑब्जेक्ट को मुक्त करने में सक्षम होना चाहिए जो रिकॉर्ड का क्षेत्र है। अगर मैं कक्षा थी, तो मैं आमतौर पर विनाशक में क्लीनअप कोड लिखूंगा। लेकिन चूंकि रिकॉर्ड प्रकार "विनाशक" पेश नहीं कर सकते हैं, इसलिए टॉब्जेक्ट (फ़ील्ड) को कॉल करना संभव होगा। फ्री;?किसी ऑब्जेक्ट को रिकॉर्ड करने के लिए कैसे रिकॉर्ड करें?

  1. एक नया एक के साथ रिकॉर्ड की जगह:

    दो उपयोग के प्रकार मैं भविष्यवाणी वहाँ हो जाएगा।

    मुझे लगता है कि यह उपयोग लागू करना आसान होगा। चूंकि रिकॉर्ड मूल्य प्रकार होते हैं और इसलिए उन्हें असाइनमेंट पर कॉपी किया जाता है, इसलिए मैं असाइनिंग ऑपरेटर को अधिभारित कर सकता हूं और पुरानी रिकॉर्ड के स्वामित्व वाली वस्तुओं को मुक्त कर सकता हूं।

    (संपादित करें: असाइनमेंट से अधिक भार में सक्षम नहीं था कि मेरे लिए एक नई जानकारी है ..।)

  2. गुंजाइश जहां रिकॉर्ड चर परिभाषित बाहर निकल रहा है।

    मैं एक निजी विधि के बारे में सोच सकता हूं जो वस्तुओं को मुक्त करता है और इस विधि को मैन्युअल रूप से दायरे उत्तेजना पर बुलाया जा सकता है। लेकिन, यह वही प्रश्न है: इसे और अधिक रिकॉर्ड करने के लिए कैसे? यह व्यवहार तरह के एक वर्ग की तरह लगता है ...

यहां एक नमूना (नहीं इरादा उपयोग और स्पष्ट रूप से) है:

TProperties = record 
    ... some other spesific typed fields: Integers, pointers etc.. 
    FBaseData: Pointer; 

    FAdditionalData: TList<Pointer>; 
    //FAdditionalData: array of Pointer; this was the first intended definition 
end; 

मान लें,

FAdditionalData:=TList<Pointer>.Crete; 

बुलाया

जैसे सार्वजनिक रूप से फ़ील्ड तक पहुंचकर रिकॉर्ड कन्स्ट्रक्टर या रिकॉर्ड वर्चुअल स्कोप में मैन्युअल रूप से
procedure TFormX.ButtonXClick(Sender: TObject); 
var 
    rec: TProperties; 
begin 
    //rec:=TProperties.Create(with some parameters); 

    rec.FAdditionalData:=TList<Pointer>.Create; 

    //do some work with rec 
end; 

ButtonClick गुंजाइश आरईसी अधिक नहीं है, लेकिन एक TList अभी भी अपने अस्तित्व जो मेमोरी लीक करने का कारण बनता रहता है ...

+1

रिकॉर्ड असाइनमेंट ओवरलोड नहीं किया जा सकता है। – kludg

+0

मुझे इसके बारे में पता नहीं था (पहले कभी नहीं चाहिए), लेकिन मैंने इसे अभी सीखा है :) हाँ, यह अधिभारित करने में सक्षम नहीं था ... –

उत्तर

10

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

हालांकि आप क्या कर सकते हैं एक गार्ड इंटरफेस जोड़ने के लिए जो वस्तु के जीवनकाल का प्रबंधन करेगा।

TMyRecord = record 
    obj: TMyObject; 
    guard: IInterface; 
end; 

आप यह सुनिश्चित करें कि TMyObject संदर्भ गिनती द्वारा अपने जीवनकाल का प्रबंधन करता है बनाने की जरूरत है। उदाहरण के लिए TInterfacedObject से प्राप्त करके।

जब आप रिकॉर्ड आरंभ आप ऐसा करते हैं:

rec.obj := TMyObject.Create; 
rec.guard := rec.obj; 

इस बिंदु पर, रिकॉर्ड की guard क्षेत्र अब अपनी वस्तु के जीवनकाल का प्रबंधन करेगा।

वास्तव में, यदि आप इस विचार को और आगे बढ़ाना चाहते हैं, तो आप वस्तुओं के जीवनकाल की रक्षा के लिए एक समर्पित कक्षा का निर्माण कर सकते हैं। तब वह आपको आपकी कक्षा पर IInterface लागू करने के लिए बाध्य नहीं करता है। वेब पर बहुत सारे उदाहरण हैं जो तकनीक को चित्रित करते हैं। उदाहरण के लिए मैं Smart Pointers शीर्षक वाले जैरोड होलिंगवर्थ के लेख की पेशकश करता हूं, और बैरी केली का शीर्षक Reference-counted pointers, revisited है। वहां बहुत सारे हैं। यह एक पुरानी चाल है!

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

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

+7

मैं पहले अंतिम अनुच्छेद के साथ अग्रणी सुझाव देना चाहता हूं। रिकॉर्ड्स में कक्षाएं रखना बग्गी कोड का एक तेज मार्ग है यदि कोई भी जीवनभर प्रबंधन के साथ बहुत सावधान नहीं है। – afrazier

+0

बहुत ही जानकारीपूर्ण उत्तर, धन्यवाद श्री हेफरन .. मैं उन तरीकों का प्रयोग करूँगा। मुझे डिज़ाइन के साथ और स्पष्ट होने के लिए प्रश्न को अपडेट करने की आवश्यकता है। ऑब्जेक्ट फ़ील्ड्स ** TList ** s हैं, लेकिन ऐसा लगता है कि मैं इसे पहले स्थान पर वापस कर दूंगा: ** पॉइंटर ** –

+1

डायनामिक सरणी का उपयोग जीवन समय प्रबंधन को हल करता है। आप गतिशील सरणी का उपयोग करना आसान बनाने के लिए Synopse से उत्कृष्ट 'TDynArray' का उपयोग करने पर विचार कर सकते हैं। –

3

मुझे याद है कि किसी ने TLifetimeWatcher नामक कक्षा बनाई है।

TLifetimeWatcher = class(TInterfacedObject) 
private 
    fInstance: TObject; 
    fProc: TProc; 
public 
    constructor Create(instance: TObject); overload; 
    constructor Create(instance: TObject; proc: TProc); overload; 
    destructor Destroy; override; 
end; 

// (सफाई) proc नाशक अगर सौंपा में निष्पादित किया जाएगा, अन्यथा उदाहरण नि: शुल्क विधि लागू द्वारा मुक्त हो जाएगा: मूल रूप से, यह की तरह लग रहा है।

+0

यह मेरे उत्तर में उल्लिखित मूल दृष्टिकोण है। कार्यान्वयन के बिना, यह बहुत उपयोग नहीं है। –

+2

'कोईोन' बैरी केली है - http://blog.barrkel.com/2008/09/smart-pointers-in-delphi.html – kludg