2014-10-01 33 views
11

aşağıdaki düşünün yöntem türlerini çözme değil:Jenerik doğru

{$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. 

Bu Şimdi listeden bir prosedür atamak istediğiniz varsayalım

foo 
bar 

beklenen çıktıyı üretir. Yukarıdaki gibi numaralandırma işleri.

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

Ama bu bir derleyici hatası atar: Bu da çalışır Yani

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

beri iki kat garip

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

... Ne oluyor?

Bu, Delphi'nin daha yeni sürümlerini de etkiler mi? Bu işe yaraması için makul bir beklenti varsa (eğer olduğunu düşünüyorum), QC cezbediyorum.

cevap

13

Bu bir derleyici hatası değildir, ne de bu sorun jenerik kullanımıyla ilgili değildir. Hem First hem de Last işlevleri, derleyicinin onları çağırmak isteyip istemediğinizi veya bunları referans alıp almadığınızı anlatamaması için işlev görür. Açık olun ve derleyicinin, parens sağlayarak fonksiyonu çağırmak istediğinizi bilmesini sağlayın.

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

Yine prosedürler ve işlevler çağrılırken parenslerin ihmal edilmesine izin verme kararı ile yakalandınız. Bu tasarım kararı, yapıldığında o kadar çekici görünmekle birlikte, modern kodlama stillerinde usulel tiplerin çok geniş bir şekilde kullanılmakta olduğu daha az gözükmektedir.

ProcList.First yazdığınızda, derleyici bir belirsizlikle karşılaşır. İşlevi çağırmak mı istiyorsun yoksa işleve bir prosedür tipi olarak başvurmak mı istiyorsun? Birçok senaryoda, derleyici belirsizliği çözemez, ancak burada, ifadenin bir görev operatörünün sağ tarafında bulunduğu durum bu değildir. Bu belirsizlikle karşılaşıldığında derleyici, işleve başvurmak istediğinizi varsayar.

Diğer seçim daha kötüyse, bu seçimi alır. En azından bu şekilde parantezleri temin edebilir ve açıkça çağrılacak fonksiyon için kastettiğinizi gösterirsiniz. Derleyici diğer yöne gitmişse, o zaman işleve başvurmak istediğini söylemenin bir yolunu aramış olacaktın. Son olarak bir kenara göre, First ve Last'un mülkler olarak uygulanmış olması durumunda, herhangi bir belirsizlik olmazdı.

+2

C#, C, C++, Python ve diğer dillerden. VB dışında. Kendinizi bir boyut ikiye bulduğunuzda ve diğer üye VB olduğunda daima kötüdür! –

+0

Ve AFAIK, Swift, o zaman üçlü bir takım haline gelir. –