2012-01-23 23 views
5

Dato il seguente frammento di codice:TCustomAttribute - "espressione costante previsto" errore di compilazione

type 
    MyIntf = interface 
    ['{C6184693-663E-419F-B2DA-4DA1A0E33417}'] 
    procedure Foo; 
    end; 

    InvisiblePropInterfaces = class(TCustomAttribute) 
    private 
    FGUIDS: array of TGUID; 
    public 
    constructor Create(const GUIDS: array of TGUID); 
    end; 

    [InvisiblePropInterfaces([MyIntf])] // <-- Constant expression expected error 
    TMyClass = class(TInterfacedObject, MyIntf) 
    procedure Foo; 
    end; 

Perché il compilatore che questo non è un'espressione costante? Ma dato che utilizzo InvisiblePropInterfaces come questo, il compilatore è semplicemente felice?

... 
var 
    I: InvisiblePropInterfaces; 
begin 
    I:= InvisiblePropInterfaces.Create([MyIntf]); 
... 

risposta

6

La sezione pertinente della attributes documentation è questo:

È importante comprendere che i valori passati al costruttore dell'attributo devono essere espressioni costanti. Poiché tali valori devono essere incorporati direttamente nel binario risultante, è impossibile passare un'espressione che richiede una valutazione in fase di esecuzione. Ciò solleva alcune limitazioni alle informazioni che possono essere passate all'attributo in fase di compilazione:

  • Sono consentite solo espressioni costanti, inclusi insiemi, stringhe e espressioni ordinali.
  • i parametri out e var non possono essere utilizzati, poiché richiedono la valutazione in fase di esecuzione degli indirizzi dei parametri passati.
  • Non è possibile utilizzare Addr() intrinsec e @ operator.
  • L'operatore TypeInfo() può essere utilizzato per passare informazioni sul tipo, poiché gli indirizzi dei blocchi RTTI sono noti al momento della compilazione.
  • I riferimenti di classe sono consentiti, poiché gli indirizzi della metaclass (come nel caso di TypeInfo()) sono noti al momento della compilazione.

Il punto chiave è che un constant expression è un termine tecnico Pascal che non è la stessa cosa di una costante. Sospetto che questa sia la radice della confusione.

Poiché non è possibile avere un'espressione costante che può essere passata a un TGUID, non si è fortunati con il proprio attributo. In effetti è altrettanto impossibile avere un'espressione costante che può essere passata a un parametro di array aperto.

Suppongo che si possa usare la rappresentazione di stringa dello GUID per risolvere l'enigma ma che vi lascerà con la duplicazione disordinata e l'impossibilità di passare gli array di GUID.

+0

sembra che io non abbia fortuna con il mio primo vero uso di attributi. Bene, allora devo cambiare il mio design e semplicemente decorare le mie classi con un'altra interfaccia, qualcosa del tipo: IInvisiblePropInterfaces = funzione dell'interfaccia GetGuids: array di TGuid – iamjoosy

-2

Erm, perché hai detto di aspettarsi una

TInvisiblePropInterfaces.Create (GUID const: array di TGUID);

tuo attributo sa assolutamente nulla di MyIntf

+1

il compilatore può recuperare un GUID da un tipo di interfaccia, quindi è assolutamente legale fornire un tipo di interfaccia (dato che ha un GUID) quando è previsto un tipo TGUID. Vedi anche la mia domanda modificata. – iamjoosy

+0

L'attributo non è * previsto * per sapere qualcosa sull'interfaccia, * ancora *. Ecco perché è fornito come parametro. E la tua logica non ha senso: il compilatore si lamenta che qualcosa * non è * un'espressione costante perché gli abbiamo detto di aspettarsene uno?Anche se la dichiarazione * ha * dice al compilatore di aspettarsi un'espressione costante (non lo fa), si limita a dire al compilatore di aspettarsi che uno non sia un motivo sufficiente per dirci che qualcosa * non è * uno. La domanda chiede perché il compilatore pensa che l'espressione data non sia costante, non perché il compilatore si aspetti un'espressione costante. –

+0

Mi spiace che tu mi abbia perso. "Perché il comiler pensa che non sia una costante". Indovina fortunato ?, generatore di numeri casuali, ha telefonato ad un amico, o potrebbe essere, solo potrebbe essere, da qualche parte qualcuno ha detto che non era uno ...... –

1

Questa è una limitazione nota. TGUID è dichiarato come un tipo di record e non è possibile creare un'espressione costante di record.

+1

non è vero. Puoi semplicemente chiamare InvisiblePropInterfaces.Create ([MyIntf]) senza problemi. Sembra che nel suo contesto attributo non si compili. – iamjoosy

+1

Quando lo si chiama manualmente, non deve più essere un'espressione costante. –

+0

@Rob, ma is ([MyIntf]) non è un'espressione costante? – iamjoosy

Problemi correlati