20

considerar:Delphi: ¿Todas las constantes son constantes, pero algunas son más constantes que otras?

const 
    clHotlight: TColor = $00FF9933; 
    clLink = clHotLight; //alias of clHotlight 

[Error] file.pas: Constant expression expected 

y el texto alternativo que funciona:

const 
    clHotlight = TColor($00FF9933); 
    clLink = clHotLight; //alias of clHotlight 

Explain.


luego considerar:

const 
    AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; 
    SuperuserGUID = AdministratorGUID; //alias of AdministratorGUID 

[Error] file.pas: Constant expression expected 

y corregir.

Editar: Palabra clave agregada const antes de las declaraciones; alguien no creía que fueran const.

+0

Esto me parece que acaba de cortar y pegar una tarea, sin siquiera molestarse en volver a escribirla un poco. –

+4

No realmente. Este no es el tipo de cosas en las que obtendrías una tarea asignada. Me parece que vagabundo en un rincón oscuro, y simplemente no está expresando su pregunta de la mejor manera posible. –

+1

@Jerry Coffin: no he tenido tareas desde 1997; asumiendo que el proyecto de EE de 4to año cuenta como tarea. –

Respuesta

22

clHotlight: TColor = $00FF9933; no es una constante, sino una constante mecanografiado (= variable estática), es decir, el compilador se reserva una ranura en la memoria para un TColor que contendrá el valor $00FF9933 inicialmente en tiempo de ejecución.
Debido a que el valor se puede cambiar más tarde (con la opción asignable Const ON), no es una constante real y no puede ser aceptado por el compilador en clLink = clHotLight;

clHotlight = TColor($00FF9933); está estrictamente lo mismo que clHotlight = $00FF9933;
Es un verdadero constante y el compilador reemplazará clHotlight por su valor $00FF9933 donde aparezca en el código. Y para clLink también.

leído en este SO pregunta (In Delphi 7, why can I assign a value to a const?) y todas las buenas respuestas allí ...

EDIT: sobre TGUID ...
El problema es que escribir AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; no es adecuada.
Está utilizando compilador magic para llamar al StringToGUID detrás de la escena, lo que permite la conveniencia de expresar el GUID como una cadena que no son por naturaleza. Ellos son registros.

Por lo tanto, intentar AdministratorGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; no funcionará. Eso no es un GUID ...

Una solución es tener un mecanografiadas constantes y variables de apuntando a la misma área de memoria usando la directiva absolute:

const 
    AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; 
var 
    SuperuserGUID: TGUID absolute AdministratorGUID; //alias of AdministratorGUID 
    RootGUID: TGUID absolute AdministratorGUID;  //alias of AdministratorGUID 
+0

veo lo que usted y la otra pregunta SO están diciendo. Pero, ¿qué sintaxis puedo usar para el TGUID para hacer que funcione la sintaxis deseada, por ejemplo 'SuperuserGUID = AdministratorGUID; RootGUID = AdministratorGUID; '(es decir, donde la constante es un registro) ¿O no es posible en Delphi? –

+0

Ver mi edición en la respuesta anterior. –

5
clHotlight: TColor = $00FF9933; 
     ^

está declarando clHotlight como 'variables' (bueno, bien un 'asignable constante' si has permitido esto en las opciones del compilador) por medio de la :.

Como has encontrado, declarando:

clHotlight = TColor($00FF9933); 

no hace ninguna asignación de clHotlight hasta que se especifica más adelante.

Lo mismo se aplica a su GUID.

+0

¡Pero no tengo marcada la opción "Constantes tipeados asignables"! :( –

+2

Eso no importa, Ian. La opción solo controla si son asignables. No controla la forma en que están almacenados. –

7

Probé este código:

const 
    CAnswer1 = 42; 
    CAnswer2 : Integer = 42; 

    var 
    LAnswer : Integer; 

    begin 
    LAnswer := CAnswer1; 
    LAnswer := CAnswer2; 
    end; 

y aquí está el código producido:

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 

Tiene usted razón: algunas constantes son más constantes que otros. La segunda constante en realidad es tratada por el compilador como una variable.

+0

+1 para una buena cantidad de trabajo y explicación de la prueba de concepto –

1

bienvenida a la evolución de Delphi . en delphi 1 & 2, no puede asignar un valor de constante inicial a una var global (ej: var xVar: Integer = 1). La única forma en que puede hacer eso es usar const xVar: Integer = 1) y en algunos lugares en sus códigos, puede cambiarlo a algo si lo desea. Hasta que se deshagan de esta característica antigua, no se puede usar la construcción "const xVar: Integer" como un valor constante.

Saludos surge Un Pham

4

El problema porque un escrito constante no es, en verdad, una constante, como se ha explicado con mayor o menor claridad y el éxito de los demás.

Lo que no ha sido aún demostrado es la forma de evitar el problema (en un gran número de casos), aunque un par llegó tentadoramente cerca de renunciar a ese secreto ... :)

En su caso específico se puede evitar el problema invirtiendo el "solapamiento" del valor y de la declaración de constante escrito de la siguiente manera:

const 
    clLink = $00FF9933; 
    clHotlight: TColor = clLink; 

clLink ofrece ahora su verdadera constante y clHotlight es la constante con tipo que tiene el mismo valor que clLink.

Para el GUID de la misma técnica se puede utilizar, pero hay que tener en cuenta la expresión de la constante normal utilizado para inicializar una constante GUID escrito - que no utiliza un registro, pero una cadena literal simple, así:

const 
    ID_CONSTANT = '{AA1C8AF2-C290-40AB-9CF5-2888A46E1660}'; 
    GUID_CONSTANT: TGUID = ID_CONSTANT; 

NOTA: Tales constantes GUID son perfectamente utilizable en todos los lugares donde se requieren TGUID 's, por ejemplo, IsEqualGUID (tguid, GUID_CONSTANT), etc.

+1

Desafortunadamente, enturbia la declaración GUID debido a esta incoherencia: ID_CONSTANT es una cadena y no un TGUID a pesar de una declaración que parece ser la misma que la declaración const tipada de un TGUID. –

+0

No estoy seguro de dónde/por qué/cómo se hace "fangoso". No puedo pensar en una ocasión en la que se requiera/use un verdadero valor GUID de "expresión constante". El lugar habitual en el que aparece esto aparece en una declaración de "caso", y no se puede "presentar caso" en un valor GUID, incluso si fuera posible declarar registros constantes verdaderos. – Deltics

+0

Usamos GUID constantes todo el tiempo. El más útil es 'NULL_GUID: TGUID = '{00000000-0000-0000-0000-000000000000}'; if IsEqualGUID (clave, NULL_GUID) then'. Otro ejemplo es el que vio, verificando si se trata de un usuario predefinido en particular. Otro ejemplo es declarar un COM ** clsid ** constante, por ejemplo: 'CLASS_UIRibbonFramework: TGUID = '{926749FA-2615-4987-8845-C33E65F2B957}';' –

2

El lado derecho de una declaración de constante debe ser una "expresión constante", que se define como "una expresión constante es una expresión que el compilador puede evaluar sin ejecutar el programa en que ocurre ". Puede encontrar toda la sintaxis aceptada para la expresión constante en la guía de idiomas. Tenga en cuenta que la guía de idioma establece explícitamente que "las constantes tipadas no pueden aparecer en expresiones constantes". - y es por eso que sus declaraciones fallan, tanto clHotlight: TColor = $ 00FF9933; y AdministratorGUID: TGUID = ...; son constantes tipadas. Además, la expresión constante no puede incluir llamadas a funciones excepto las enumeradas en la guía de idioma (es decir, Length(), SizeOf() y algunas otras) que el compilador puede calcular en tiempo de compilación. Vuelva a escribir de esta manera:

const 
    AdminGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; 
    AdministratorGUID: TGUID = AdminGUID; 
    SuperuserGUID: TGUID = AdminGUID; 

Y funcionará.