2009-02-16 12 views
8

टाइपइन्फो (प्रकार) निर्दिष्ट प्रकार के बारे में जानकारी देता है, क्या var के typeinfo को जानने का कोई तरीका है?कैसे पता चले कि एक प्रकार किस प्रकार है?

var 
    S: string; 
    Instance: IObjectType; 
    Obj: TDBGrid; 
    Info: PTypeInfo; 
begin 
    Info:= TypeInfo(S); 
    Info:= TypeInfo(Instance); 
    Info:= TypeInfo(Obj); 
end 

इस कोड को प्रस्तुत करती है:

[डीसीसी त्रुटि] Unit1.pas (354): E2133 TYPEINFO मानक समारोह एक प्रकार पहचानकर्ता

उम्मीद मैं जानता हूँ कि एक गैर instantiated var केवल एक सूचक है पता। संकलन समय पर, कंपाइलर पार्स और टाइप सुरक्षा जांच करते हैं।

रन टाइम पर, क्या एक var के बारे में कुछ और जानने के लिए कोई तरीका है, केवल अपना पता पास कर रहा है?

उत्तर

2

मुझे पता नहीं है। आप कक्षा के प्रकाशित गुणों पर आरटीटीआई (रन टाइम टाइप सूचना) प्राप्त कर सकते हैं, लेकिन स्ट्रिंग्स और पूर्णांक जैसे "सामान्य" चर के लिए नहीं। जानकारी बस वहां नहीं है।

इसके अलावा, एक प्रकार से गुजरने के बिना आप एक var पास कर सकते हैं, एक सामान्य प्रकार (जे 2008, के रूप में), या एक untyped पैरामीटर के रूप में या तो एक सामान्य टॉब्जेक्ट पैरामीटर का उपयोग करना है। मैं इसे पारित करने का एक और तरीका नहीं सोच सकता जो संकलन भी करेगा।

+1

आपके पास "प्रक्रिया परीक्षण (var AUntypedParam)" (या "var" के बजाय "const" या "out" के साथ) हो सकता है। –

+0

क्षमा करें। मेरा जवाब "untyped सूचक" के बजाय "untyped पैरामीटर" कहा जाना चाहिए था। सही किया। –

28

सं

सबसे पहले, वहाँ एक जैसी कोई चीज नहीं है "गैर instantiated चर।" आप इसे अपना नाम टाइप करने और अपनी स्रोत फ़ाइल में टाइप करने के केवल कार्य द्वारा तुरंत चालू करते हैं।

दूसरा, आप पहले से ही जानते हैं कि एक वैरिएबल के बारे में जानना आपके स्रोत कोड में देखकर है। एक बार आपके प्रोग्राम को संकलित करने के बाद परिवर्तनीय मौजूद है। उसके बाद, यह सब सिर्फ बिट्स है।

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

किसी भी समय आप एक चर के साथ जुड़े प्रकार की प्रकार की जानकारी प्राप्त करने के लिए TypeInfo का उपयोग करना चाहते हैं, तो आप सीधे उस प्रकार का नाम भी दे सकते हैं जिसमें आप रुचि रखते हैं; यदि चर दायरे में है, तो आप इसकी घोषणा पा सकते हैं और घोषित प्रकार का उपयोग अपने कॉल में TypeInfo पर कर सकते हैं।

यदि आप किसी फ़ंक्शन में मनमाने ढंग से पता करना चाहते हैं और उस फ़ंक्शन को स्वयं के लिए प्रकार की जानकारी मिलती है, तो आप भाग्य से बाहर हैं। आपको इसके अतिरिक्त PTypeInfo मान को अतिरिक्त पैरामीटर के रूप में पास करने की आवश्यकता होगी। यही वह अंतर्निहित डेल्फी कार्य करता है। उदाहरण के लिए, जब आप पॉइंटर चर पर New पर कॉल करते हैं, तो संकलक एक अतिरिक्त पैरामीटर डालता है जिसमें आपके द्वारा आवंटित किए जाने वाले प्रकार के लिए PTypeInfo मान होता है। जब आप गतिशील सरणी पर SetLength पर कॉल करते हैं, तो कंपाइलर सरणी प्रकार के लिए PTypeInfo मान डालता है।

The answer that you gave सुझाव देता है कि आप जो कुछ भी मांगे उसके अलावा कुछ और ढूंढ रहे हैं।अपने प्रश्न को देखते हुए, मैंने सोचा था कि आप एक काल्पनिक समारोह है कि इस कोड को पूरा कर सके देख रहे थे:

function GetVariableTypeInfo(pvar: Pointer): PTypeInfo; 
begin 
    if not Assigned(pvar) then 
    Result := nil 
    else if IsClass(PPointer(pvar)^) then 
    Result := PClass(pvar).ClassInfo 
    else if IsObject(PPointer(pvar)^) then 
    Result := PObject(pvar).ClassInfo 
    else 
    raise EUnknownResult.Create; 
end; 

यह स्पष्ट रूप से S लिए काम नहीं करेगा:

var 
    S: string; 
    Instance: IObjectType; 
    Obj: TDBGrid; 
    Info: PTypeInfo; 
begin 
    Info:= GetVariableTypeInfo(@S); 
    Assert(Info = TypeInfo(string)); 

    Info:= GetVariableTypeInfo(@Instance); 
    Assert(Info = TypeInfo(IObjectType)); 

    Info:= GetVariableTypeInfo(@Obj); 
    Assert(Info = TypeInfo(TDBGrid)); 
end; 

के IsClass and IsObject functions from the JCL का उपयोग करें कि समारोह के निर्माण के लिए करते हैं या Instance ऊपर है, लेकिन देखते हैं क्या Obj साथ होता है:

Info := GetVariableTypeInfo(@Obj); 

कि एक पहुँच देना चाहिए उल्लंघन। Obj का कोई मूल्य नहीं है, इसलिए IsClass और IsObject दोनों एक अनिर्दिष्ट स्मृति पता पढ़ रहे होंगे, शायद आपकी प्रक्रिया से संबंधित कोई भी नहीं। आपने एक दिनचर्या मांगी है जो एक चर के पते को अपने इनपुट के रूप में उपयोग करेगी, लेकिन केवल पता पर्याप्त नहीं है।

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

// This code will yield no assertion failures. 
var 
    p: Pointer; 
    o: TObject; 
    a: array of Integer; 
begin 
    p := TDBGrid; 
    Assert(IsClass(p)); 

    p := TForm.Create(nil); 
    Assert(IsObject(p)); 

    // So far, so good. Works just as expected. 
    // Now things get interesting: 

    Pointer(a) := p; 
    Assert(IsObject(a)); 
    Pointer(a) := nil; 
    // A dynamic array is an object? Hmm. 

    o := nil; 
    try 
    IsObject(o); 
    Assert(False); 
    except 
    on e: TObject do 
     Assert(e is EAccessViolation); 
    end; 
    // The variable is clearly a TObject, but since it 
    // doesn't hold a reference to an object, IsObject 
    // can't check whether its class field looks like 
    // a valid class reference. 
end; 

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

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

var 
    c: TClass; 
begin 
    c := TDBGrid; 
    Assert(IsClass(c)); 
    Assert(not IsClass(@c)); // Address of variable 
    Assert(IsObject(@c)); // Address of variable is an object? 
end; 

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

कुल मिलाकर, आप गलत सवाल पूछ रहे हैं। यह पूछने के बजाय कि आप एक चर के प्रकार या स्मृति में किसी प्रकार के मान को निर्धारित करते हैं, आपको यह पूछना चाहिए कि आप अपने आप को उस स्थिति में कैसे प्राप्त कर चुके हैं जहां आप पहले से ही अपने चर के प्रकार और आपके डेटा नहीं जानते हैं।

+0

उत्तर पहले से ही अच्छा था, लेकिन आपके संपादन ने इसे और भी बेहतर बना दिया। +1। – mghie

+0

मुझे खेद है, मेरे जबड़े एक पल के लिए गिरा दिया ... +1 – Wodzu

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