Delphi: toutes les constantes sont constantes, mais certaines sont plus constantes que d'autres?
Considérez:
const
clHotlight: TColor = $00FF9933;
clLink = clHotLight; //alias of clHotlight
[Error] file.pas: Constant expression expected
Et le libellé alternatif qui fonctionne:
const
clHotlight = TColor($00FF9933);
clLink = clHotLight; //alias of clHotlight
Expliquez.
Considérons alors:
const
AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
SuperuserGUID = AdministratorGUID; //alias of AdministratorGUID
[Error] file.pas: Constant expression expected
Et fixer.
Edit: mot-clé ajouté const
avant les déclarations; quelqu'un ne croyait pas qu'ils étaient const.
7 réponses
clHotlight: TColor = $00FF9933;
n'est pas une constante mais une constante typée (=variable statique), c'est-à-dire que le compilateur réserve un slot en mémoire pour un TColor qui contiendra la valeur $00FF9933
initialement au moment de l'exécution.
Comme cette valeur peut être modifiée plus tard (avec L'option Const Assignable activée), elle n'est pas une constante réelle et ne peut pas être acceptée par le compilateur dans clLink = clHotLight;
clHotlight = TColor($00FF9933);
est strictement la même que clHotlight = $00FF9933;
C'est une vraie constante et le compilateur remplacera clHotlight
par sa valeur $00FF9933
partout où il apparaît dans le code. Et pour clLink
aussi.
Lire sur cette question SO (dans Delphi 7, Pourquoi puis-je attribuer une valeur à un const?) et toutes les bonnes réponses...
EDIT: à propos de TGUID...
Le problème est que l'écriture AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
n'est pas correcte.
Il utilise de la magie du compilateur pour appeler StringToGUID
derrière la scène, ce qui permet d'exprimer le GUID sous forme de chaîne ce qu'ils ne sont pas par nature. Ils sont les dossiers.
Donc, essayer {[11] } ne fonctionnera pas. Ce N'est pas un GUID...
Une solution de contournement est d'avoir typé constante et variables pointant vers la même zone de mémoire à l'aide de la absolute
directive:
const
AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
var
SuperuserGUID: TGUID absolute AdministratorGUID; //alias of AdministratorGUID
RootGUID: TGUID absolute AdministratorGUID; //alias of AdministratorGUID
J'ai essayé ce code :
const
CAnswer1 = 42;
CAnswer2 : Integer = 42;
var
LAnswer : Integer;
begin
LAnswer := CAnswer1;
LAnswer := CAnswer2;
end;
Et voici le code produit:
Project9.dpr.18: LAnswer := CAnswer1;
004101AC C7056C6E41002A00 mov [$00416e6c],$0000002a //<- assign a hard-coded "42" value
Project9.dpr.19: LAnswer := CAnswer2;
004101B6 A1701C4100 mov eax,[$00411c70] //<- fetch a variable's content
004101BB A36C6E4100 mov [$00416e6c],eax //<- assign this content
Vous avez raison: certaines constantes sont plus constantes que d'autres. La deuxième constante est en fait traitée par le compilateur comme une variable.
clHotlight: TColor = $00FF9933;
^
Déclare clHotlight
en tant que 'variable '(Eh bien, ok une 'constante assignable' si vous l'avez autorisé dans les options du compilateur) au moyen du :
.
Comme vous l'avez trouvé, déclarant:
clHotlight = TColor($00FF9933);
Ne fait aucune allocation de clHotlight
jusqu'à ce qu'elle soit spécifiée plus tard.
La même chose s'applique à votre GUID.
Le problème se pose parce qu'une constante typée n'est pas, vraiment, une constante, comme cela a été expliqué avec plus ou moins de clarté et de succès par d'autres.
Ce qui n'a pas encore été montré, c'est comment contourner le problème (dans un grand nombre de cas), bien qu'un couple ait failli abandonner ce secret... :)
Dans votre cas spécifique, vous pouvez contourner le problème en inversant le "aliasing" de la valeur et la déclaration de constante typée comme suit:
const
clLink = $00FF9933;
clHotlight: TColor = clLink;
ClLink fournit maintenant votre véritable constante et clHotlight est typé constante qui a la même valeur que clLink.
Pour les GUID, la même technique peut être utilisée, mais vous devez garder à l'esprit l'expression constante normale utilisée pour initialiser une constante GUID typée - elle n'utilise pas un enregistrement mais une simple chaîne littérale, donc:
const
ID_CONSTANT = '{AA1C8AF2-C290-40AB-9CF5-2888A46E1660}';
GUID_CONSTANT: TGUID = ID_CONSTANT;
NOTE: {[10] } de telles constantes GUID sont parfaitement utilisables dans tous les endroits où TGUID sont obligatoires, par exemple IsEqualGUID (tguid, GUID_CONSTANT ) etc.
Le côté droit d'une déclaration de constante doit être une "expression constante", qui est définie comme "une expression constante est une expression que le compilateur peut évaluer sans exécuter le programme dans lequel elle se produit". Vous pouvez trouver toute la syntaxe acceptée pour l'expression constante dans le guide de langue. Notez que le guide de langue indique explicitement "les constantes typées ne peuvent pas se produire dans les expressions constantes."- et c'est pourquoi vos déclarations échoue, à la fois clHotlight: TColor = $ 00FF9933; et AdministratorGUID: TGUID =...; sont des constantes typées. En outre, l'expression constante ne peut pas inclure les appels de fonctions à l'exception de ceux listés dans le guide de langue (C'est-à-dire Length(), SizeOf () et quelques autres) que le compilateur est capable de calculer au moment de la compilation. Réécrire de cette façon:
const
AdminGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
AdministratorGUID: TGUID = AdminGUID;
SuperuserGUID: TGUID = AdminGUID;
Et ça va marcher.
Bienvenue à Delphes évolution. dans delphi 1 & 2, vous ne pouvez pas attribuer une valeur constante initiale à une var globale (ex: var xVar: Integer = 1). La seule façon de le faire est d'utiliser const xVar: Integer = 1) et certains où dans vos codes, vous pouvez ensuite le changer en somethingelse si vous le souhaitez. Jusqu'à ce qu'ils se débarrassent de cette fonctionnalité ancienne, vous ne pouvez pas utiliser la construction "const xVar: Integer" comme valeur const.
Santé Un Pham