www org mapwingis mapwindows mapwindow español delphi runtime typeinfo

delphi - org - mapwindows 5



¿Cómo saber qué tipo es una var? (2)

No que yo sepa. Puede obtener RTTI (información de tipo de tiempo de ejecución) sobre las propiedades publicadas de una clase, pero no para variables "normales" como cadenas y enteros, etc. La información simplemente no está allí.

Además, la única forma de pasar una var sin pasar un tipo es usar un parámetro TObject genérico, un tipo genérico (D2008, como en) o un parámetro sin tipo. No puedo pensar en otra forma de pasarlo que incluso compilara.

TypeInfo (Type) devuelve la información sobre el tipo especificado, ¿hay alguna forma de conocer el typeinfo de una var?

var S: string; Instance: IObjectType; Obj: TDBGrid; Info: PTypeInfo; begin Info:= TypeInfo(S); Info:= TypeInfo(Instance); Info:= TypeInfo(Obj); end

Este código regresa:

[Error de DCC] Unit1.pas (354): la función estándar de E2133 TYPEINFO espera un identificador de tipo

Sé que una var no instanciada es solo una dirección de puntero. En tiempo de compilación, el compilador analiza y hace el tipo de verificación de seguridad.

En tiempo de ejecución, ¿hay alguna forma de saber un poco más sobre una var, solo pasando su dirección?


No.

Primero, no existe una "variable no instanciada". Lo instancia por el mero hecho de escribir su nombre y escribirlo en su archivo fuente.

En segundo lugar, ya sabes todo lo que hay que saber sobre una variable mirándola en tu código fuente. La variable deja de existir una vez que se compila su programa. Después de eso, todo es solo bits.

Un puntero solo tiene un tipo en tiempo de compilación. En tiempo de ejecución, todo lo que se puede hacer a esa dirección ya ha sido determinado. El compilador verifica eso, como ya anotó. Comprobar el tipo de variable en tiempo de ejecución solo es útil en los idiomas en los que el tipo de variable podría cambiar, como en los lenguajes dinámicos. Lo más cerca que llega Delphi es con su tipo de Variant . El tipo de la variable siempre es Variant , pero puede almacenar muchos tipos de valores en ella. Para saber qué contiene, puede usar la función VarType .

Cada vez que desee usar TypeInfo para obtener la información de tipo del tipo asociado con una variable, también puede nombrar directamente el tipo que le interesa; si la variable está dentro del alcance, puede buscar su declaración y usar el tipo declarado en su llamada a TypeInfo .

Si desea pasar una dirección arbitraria a una función y hacer que esa función descubra la información del tipo por sí misma, no tiene suerte. En su lugar, deberá pasar el valor de PTypeInfo como un parámetro adicional. Eso es lo que hacen todas las funciones Delphi integradas. Por ejemplo, cuando llama a New en una variable de puntero, el compilador inserta un parámetro adicional que contiene el valor de PTypeInfo para el tipo que está asignando. Cuando llama a SetLength en una matriz dinámica, el compilador inserta un valor de PTypeInfo para el tipo de matriz.

La respuesta que dio sugiere que está buscando algo diferente a lo que pidió. Dada tu pregunta, pensé que estabas buscando una función hipotética que pudiera satisfacer este código:

var S: string; Instance: IObjectType; Obj: TDBGrid; Info: PTypeInfo; begin Info:= GetVariableTypeInfo(@S); Assert(Info = TypeInfo(string)); Info:= GetVariableTypeInfo(@Instance); Assert(Info = TypeInfo(IObjectType)); Info:= GetVariableTypeInfo(@Obj); Assert(Info = TypeInfo(TDBGrid)); end;

IsObject funciones IsClass e IsObject del JCL para construir esa función:

function GetVariableTypeInfo(pvar: Pointer): PTypeInfo; begin if not Assigned(pvar) then Result := nil else if IsClass(PPointer(pvar)^) then Result := PClass(pvar).ClassInfo else if IsObject(PPointer(pvar)^) then Result := PObject(pvar).ClassInfo else raise EUnknownResult.Create; end;

Obviamente no funcionará para S o Instance arriba, pero veamos qué sucede con Obj :

Info := GetVariableTypeInfo(@Obj);

Eso debería dar una violación de acceso. Obj no tiene ningún valor, por lo que IsClass e IsObject leerán una dirección de memoria no especificada, probablemente no una que pertenezca a su proceso. Pediste una rutina que usaría la dirección de una variable como entrada, pero la mera dirección no es suficiente.

Ahora echemos un vistazo más de cerca a cómo IsClass y IsObject realmente se comportan. Esas funciones toman un valor arbitrario y verifican si el valor parece ser un valor del tipo dado, ya sea objeto (instancia) o clase. Úselo así:

// This code will yield no assertion failures. var p: Pointer; o: TObject; a: array of Integer; begin p := TDBGrid; Assert(IsClass(p)); p := TForm.Create(nil); Assert(IsObject(p)); // So far, so good. Works just as expected. // Now things get interesting: Pointer(a) := p; Assert(IsObject(a)); Pointer(a) := nil; // A dynamic array is an object? Hmm. o := nil; try IsObject(o); Assert(False); except on e: TObject do Assert(e is EAccessViolation); end; // The variable is clearly a TObject, but since it // doesn''t hold a reference to an object, IsObject // can''t check whether its class field looks like // a valid class reference. end;

Tenga en cuenta que las funciones no le dicen nada sobre las variables, solo sobre los valores que guardan. Realmente no consideraría esas funciones, entonces, para responder la pregunta de cómo obtener información sobre una variable.

Además, dijiste que todo lo que sabes sobre la variable es su dirección. Las funciones que encontraste no toman la dirección de una variable. Toman el valor de una variable. Aquí hay una demostración:

var c: TClass; begin c := TDBGrid; Assert(IsClass(c)); Assert(not IsClass(@c)); // Address of variable Assert(IsObject(@c)); // Address of variable is an object? end;

Podrías objetar que estoy abusando de estas funciones al pasarles lo que obviamente es basura. Pero creo que esa es la única forma en que tiene sentido hablar sobre este tema. Si sabes que nunca tendrás valores basura, entonces no necesitas la función que estás pidiendo de todos modos porque ya sabes lo suficiente sobre tu programa para usar tipos reales para tus variables.

En general, estás haciendo la pregunta incorrecta. En lugar de preguntar cómo determina el tipo de una variable o el tipo de un valor en la memoria, debería preguntar cómo se metió en la posición en la que aún no conoce los tipos de sus variables y sus datos .