2014-10-01 5 views
11

निम्नलिखित पर विचार करें:जेनेरिक्स विधि प्रकार के समाधान नहीं सही ढंग से

{$APPTYPE CONSOLE} 

uses 
    Generics.Collections; 

type 
    TObjProc = procedure of object; 
    TFoo = class 
    public procedure DoFoo; 
    public procedure DoBar; 
    end; 

procedure TFoo.DoFoo; 
begin 
    WriteLn('foo'); 
end; 

procedure TFoo.DoBar; 
begin 
    WriteLn('bar'); 
end; 

var 
    ProcList : TList<TObjProc>; 
    Foo : TFoo; 
    aProc : TObjProc; 
begin 
    Foo := TFoo.Create; 
    ProcList := TList<TObjProc>.Create; 
    ProcList.Add(Foo.DoFoo); 
    ProcList.Add(Foo.DoBar); 
    for aProc in ProcList do aProc; 
    ReadLn; 
end. 

यह

foo 
bar 

की उम्मीद उत्पादन का उत्पादन अब मान लीजिए कि हम सूची में से एक प्रक्रिया प्रदान करना चाहते हैं। उपरोक्त के रूप में काम की गणना। यह भी काम करता है:

aProc := ProcList.Items[0]; 
aProc; 

लेकिन यह एक संकलक त्रुटि फेंकता है:

aProc := ProcList.First; 
// E2010 Incompatible types: 
//'procedure, untyped pointer or untyped parameter' and 'TObjProc' 

कौन सा के बाद से

function TList<T>.First: T; 
begin 
    Result := Items[0]; 
end; 

तो दोगुना अजीब है ... क्या हो रहा है?

इस रूप में अच्छी तरह डेल्फी के नए संस्करण प्रभावित करता है? मैं क्यूसी से यह लुभाना चाहता हूं कि अगर उचित उम्मीद है कि यह काम करना चाहिए (जो मुझे लगता है)।

उत्तर

13

यह एक नहीं एक संकलक बग है, और न ही वास्तव में जेनरिक के आपके उपयोग से संबंधित इस मुद्दे है। दोनों First और Last कार्यों इसलिए संकलक नहीं बता सकता कि आप उन्हें फोन करने के लिए मतलब है, या उन्हें संदर्भ हैं। स्पष्ट रहें और संकलक को यह बताने दें कि आप माता-पिता की आपूर्ति करके फ़ंक्शन को कॉल करना चाहते हैं।

aProc := ProcList.First(); 
aProc := ProcList.Last(); 

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

जब आप ProcList.First लिखने संकलक एक अस्पष्टता सामना करता है। क्या आप फ़ंक्शन को कॉल करना चाहते हैं, या आप फ़ंक्शन को प्रक्रियात्मक प्रकार के रूप में संदर्भित करना चाहते हैं? कई स्थितियों में, संकलक अस्पष्टता को हल नहीं कर सकता है, लेकिन स्थिति यहाँ है, जहां अभिव्यक्ति एक असाइनमेंट ऑपरेटर के दाहिने हाथ की ओर पर पाया जाता है नहीं है। इस अस्पष्टता के साथ सामना करने वाला संकलक मानता है कि आप फ़ंक्शन का संदर्भ लेना चाहते हैं।

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

अंतिम तरफ के रूप में, यदि First और Last को गुणों के रूप में लागू किया गया था तो वहां कोई अस्पष्टता नहीं होगी।

+2

सी #, सी, सी ++, पायथन और हर दूसरी भाषा से। वीबी के अलावा। जब आप खुद को आकार दो के सेट में पाते हैं तो यह हमेशा खराब होता है और दूसरा सदस्य वीबी है !! –

+0

और, AFAIK, स्विफ्ट, तो फिर यह तीन का सेट बन जाता है। –

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