Delphi: Toutes les constantes sont constantes, mais certains sont plus constantes que d'autres?
-
01-10-2019 - |
Question
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érez alors:
const
AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
SuperuserGUID = AdministratorGUID; //alias of AdministratorGUID
[Error] file.pas: Constant expression expected
fix.
Edit: Ajout const
mot-clé avant les déclarations; quelqu'un ne croyait pas qu'ils étaient const.
La solution
clHotlight: TColor = $00FF9933;
est pas une constante mais une constante typée (= variable statique), à ??savoir les réserves de compilation d'une fente dans la mémoire pour un TColor qui contiendra la valeur $00FF9933
initialement au moment de l'exécution.
Parce que la valeur peut être modifiée ultérieurement (avec l'option assignable Const ON), il est une constante réelle et ne peut être acceptée par le compilateur dans clLink = clHotLight;
clHotlight = TColor($00FF9933);
est strictement le même que clHotlight = $00FF9933;
Il est une véritable constante et le compilateur remplacera clHotlight
par sa valeur $00FF9933
partout où il apparaît dans le code. Et pour clLink
ainsi.
Lire sur cette question SO ( Dans Delphi 7, pourquoi puis-je attribuer une valeur à un const? ) et toutes les bonnes réponses là ...
EDIT: environ TGUID ...
Le problème est que l'écriture AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
n'est pas bonne.
Il utilise une magie du compilateur pour appeler StringToGUID
derrière la scène, ce qui permet la commodité d'exprimer le GUID comme une chaîne dont ils ne sont pas par nature. Ce sont des dossiers.
Alors, AdministratorGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
essayer ne fonctionnera pas. Ce n'est pas un GUID ...
Une solution de contournement est d'avoir su une constante typée et Variables pointant vers la même zone de mémoire en utilisant 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
Autres conseils
J'ai essayé ce code:
const
CAnswer1 = 42;
CAnswer2 : Integer = 42;
var
LAnswer : Integer;
begin
LAnswer := CAnswer1;
LAnswer := CAnswer2;
end;
et le code produit ici:
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 seconde constante est effectivement traitée par le compilateur en tant que variable.
clHotlight: TColor = $00FF9933;
^
est clHotlight
comme déclarant « variable » (bien, ok une « constante cessible » si vous avez autorisé ce dans les options du compilateur) au moyen du :
.
Comme vous l'avez trouvé, déclarant:
clHotlight = TColor($00FF9933);
Permet aucune allocation de clHotlight
jusqu'à ce qu'il soit précisé plus tard.
Le même applique à votre GUID.
Le problème se pose car une constante typée n'est pas, vraiment, une constante, comme cela a été expliqué avec des degrés de clarté et de succès par d'autres.
Ce qui n'a pas encore été montré est de savoir comment contourner le problème (dans un grand nombre de cas), si un couple est venu terriblement près de renoncer à ce secret ...:)
Dans votre cas spécifique, vous pouvez contourner le problème en inversant le « aliasing » de la valeur et la déclaration constante typée comme suit:
const
clLink = $00FF9933;
clHotlight: TColor = clLink;
clLink fournit maintenant votre vraie constante et clHotlight est la constante typée qui a la même valeur que clLink .
Pour peut être utilisé la même technique du GUID, mais vous devez garder à l'esprit l'expression constante normale utilisée pour initialiser une constante GUID typé - il n'utilise pas d'enregistrement mais une simple chaîne de, donc:
const
ID_CONSTANT = '{AA1C8AF2-C290-40AB-9CF5-2888A46E1660}';
GUID_CONSTANT: TGUID = ID_CONSTANT;
NOTE: Ces constantes GUID sont parfaitement utilisables dans tous les endroits où TGUID 's sont nécessaires, par exemple IsEqualGUID (TGUID, GUID_CONSTANT) etc.
Le côté droit d'une déclaration constante doit être, qui est défini comme « expression constante », « une expression constante est une expression que le compilateur peut évaluer sans exécuter le programme dans lequel il se produit ». Vous pouvez trouver toute la syntaxe acceptée pour l'expression constante dans le guide linguistique. Notez que le guide de la langue énonce explicitement « constantes typées ne peut pas se produire dans des expressions constantes. » - et voilà pourquoi vos déclarations échoue, les deux clHotlight: TColor = 00FF9933 $; et AdministratorGUID: TGUID = ...; sont des constantes typées. En outre, l'expression constante ne peut pas inclure des appels de fonctions sauf celles qui figurent dans le guide de la langue (à savoir Longueur (), sizeof (), et quelques autres) que le compilateur est capable de calculer au moment de la compilation. Réécrire cette façon:
const
AdminGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
AdministratorGUID: TGUID = AdminGUID;
SuperuserGUID: TGUID = AdminGUID;
Et cela fonctionnera.
bienvenue à l'évolution Delphi. dans delphi 1 & 2, vous ne pouvez pas affecter la valeur constante initiale à une variable globale (ex: var xVar: Integer = 1). La seule façon que vous pouvez faire est en utilisant const xVar: Integer = 1) et où, dans certains codes vous, vous pouvez changer à somethingelse si on le souhaite. Jusqu'à ce qu'ils se débarrasser de cette fonctionnalité ancienne, vous ne pouvez pas utiliser « const xVar: Entier ». Construction en tant que valeur de const
Vive A Pham