如何知道 var 是什么类型?
TypeInfo(Type) 返回有关指定类型的信息,有什么方法可以知道 var 的类型信息吗?
var
S: string;
Instance: IObjectType;
Obj: TDBGrid;
Info: PTypeInfo;
begin
Info:= TypeInfo(S);
Info:= TypeInfo(Instance);
Info:= TypeInfo(Obj);
end
此代码返回:
[DCC Error] Unit1.pas(354): E2133 TYPEINFO 标准函数需要类型标识符
我知道非实例化的 var 只是一个指针地址。 在编译时,编译器会解析并进行类型安全检查。
在运行时,有没有办法只传递它的地址来更多地了解 var?
TypeInfo(Type) returns the info about the specified type, is there any way to know the typeinfo of a var?
var
S: string;
Instance: IObjectType;
Obj: TDBGrid;
Info: PTypeInfo;
begin
Info:= TypeInfo(S);
Info:= TypeInfo(Instance);
Info:= TypeInfo(Obj);
end
This code returns:
[DCC Error] Unit1.pas(354): E2133 TYPEINFO standard function expects a type identifier
I know a non instantiated var is only a pointer address.
At compile time, the compiler parses and do the type safety check.
At run time, is there any way to know a little more about a var, only passing its address?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不。
首先,不存在“非实例化变量”这样的东西。 您只需在源文件中键入其名称和类型即可实例化它。
其次,通过在源代码中查看变量,您已经了解了有关该变量的所有信息。 一旦程序被编译,变量就不再存在。 在那之后,一切都只是碎片。
指针仅在编译时具有类型。 在运行时,对该地址可以执行的所有操作都已确定。 正如您已经指出的那样,编译器会对此进行检查。 在运行时检查变量的类型仅在变量类型可能更改的语言中有用,例如在动态语言中。 Delphi 最接近的就是它的
Variant
类型。 变量的类型始终是Variant
,但您可以在其中存储多种类型的值。 要了解它包含的内容,您可以使用VarType
函数。任何时候您想要使用 TypeInfo 来获取与变量关联的类型的类型信息时,您也可以直接命名您感兴趣的类型; 如果变量在作用域内,那么您可以找到它的声明并在对
TypeInfo
的调用中使用声明的类型。如果您想将任意地址传递给函数并让该函数自行发现类型信息,那么您就不走运了。 您需要将
PTypeInfo
值作为附加参数传递。 这就是所有内置 Delphi 函数的作用。 例如,当您对指针变量调用New
时,编译器会插入一个附加参数,该参数保存您要分配的类型的PTypeInfo
值。 当您对动态数组调用SetLength
时,编译器会插入数组类型的PTypeInfo
值。您给出的答案表明您正在寻找与您要求的不同的东西。 鉴于您的问题,我认为您正在寻找一个可以满足此代码的假设函数:
让我们使用
IsClass
和IsObject
来自 JCL 的函数来构建该函数:显然不会适用于上面的
S
或Instance
,但让我们看看Obj
会发生什么:这应该会导致访问冲突。
Obj
没有值,因此IsClass
和IsObject
都将读取未指定的内存地址,可能不属于您的进程。 您要求一个使用变量地址作为输入的例程,但仅使用地址是不够的。现在让我们仔细看看
IsClass
和IsObject
的实际行为。 这些函数采用任意值并检查该值是否看起来它可能是给定类型的值,无论是对象(实例)还是类。 像这样使用它:请注意,函数不会告诉您有关变量的任何信息,只会告诉您它们所保存的值。 那么,我不会真正考虑这些函数来回答如何获取有关变量的类型信息的问题。
此外,您说您对变量的了解只是它的地址。 您找到的函数不采用变量的地址。 它们获取变量的值。 这是一个演示:
您可能会反对我通过将明显垃圾的内容传递给这些函数来滥用这些函数。 但我认为这是谈论这个话题的唯一方式。 如果您知道永远不会有垃圾值,那么您就不需要您所要求的函数,因为您已经足够了解您的程序,可以为变量使用真实类型。
总的来说,你问了错误的问题。 你不应该问如何确定变量的类型或内存中值的类型,你应该问你如何让自己陷入还不知道变量和数据的类型的境地< /强>。
No.
First, there's no such thing as a "non-instantiated variable." You instantiate it by the mere act of typing its name and type into your source file.
Second, you already know all there is to know about a variable by looking at it in your source code. The variable ceases to exist once your program is compiled. After that, it's all just bits.
A pointer only has a type at compile time. At run time, everything that can be done to that address has already been determined. The compiler checks for that, as you already noted. Checking the type of a variable at run time is only useful in languages where a variable's type could change, as in dynamic languages. The closest Delphi comes to that is with its
Variant
type. The type of the variable is alwaysVariant
, but you can store many types of values in it. To find out what it holds, you can use theVarType
function.Any time you could want to use
TypeInfo
to get the type information of the type associated with a variable, you can also directly name the type you're interested in; if the variable is in scope, then you can go find its declaration and use the declared type in your call toTypeInfo
.If you want to pass an arbitrary address to a function and have that function discover the type information for itself, you're out of luck. You will instead need to pass the
PTypeInfo
value as an additional parameter. That's what all the built-in Delphi functions do. For example, when you callNew
on a pointer variable, the compiler inserts an additional parameter that holds thePTypeInfo
value for the type you're allocating. When you callSetLength
on a dynamic array, the compiler inserts aPTypeInfo
value for the array type.The answer that you gave suggests that you're looking for something other than what you asked for. Given your question, I thought you were looking for a hypothetical function that could satisfy this code:
Let's use the
IsClass
andIsObject
functions from the JCL to build that function:It obviously won't work for
S
orInstance
above, but let's see what happens withObj
:That should give an access violation.
Obj
has no value, soIsClass
andIsObject
both will be reading an unspecified memory address, probably not one that belongs to your process. You asked for a routine that would use a variable's address as its input, but the mere address isn't enough.Now let's take a closer look at how
IsClass
andIsObject
really behave. Those functions take an arbitrary value and check whether the value looks like it might be a value of the given kind, either object (instance) or class. Use it like this:Notice that the functions tell you nothing about the variables, only about the values they hold. I wouldn't really consider those functions, then, to answer the question of how to get type information about a variable.
Furthermore, you said that all you know about the variable is its address. The functions you found do not take the address of a variable. They take the value of a variable. Here's a demonstration:
You might object to how I'm abusing these functions by passing what's obviously garbage into them. But I think that's the only way it makes sense to talk about this topic. If you know you'll never have garbage values, then you don't need the function you're asking for anyway because you already know enough about your program to use real types for your variables.
Overall, you're asking the wrong question. Instead of asking how you determine the type of a variable or the type of a value in memory, you should be asking how you got yourself into the position where you don't already know the types of your variables and your data.
使用泛型,现在可以在不指定类型的情况下获取类型信息。
某些用户表示以下代码无法正确编译。
从 Delphi 10 Seattle 版本 23.0.20618.2753 开始,它编译时没有错误,如下面的屏幕截图所示。
With generics, it is now possible to get the type info without specifying it.
Certain users indicated the following code doesn't compile without errors.
As of Delphi 10 Seattle, version 23.0.20618.2753, it compiles without errors, as seen below in the screenshot.
从来没听说过。 您可以获取类的已发布属性的 RTTI(运行时类型信息),但不能获取字符串和整数等“普通”变量。 这些信息根本不存在。
此外,在不传递类型的情况下传递 var 的唯一方法是使用泛型 TObject 参数、泛型类型(D2008,如 中)或作为无类型参数。 我想不出另一种可以编译的传递它的方法。
Not that I know of. You can get RTTI (Run Time Type Information) on published properties of a class, but not for "normal" variables like strings and integers and so forth. The information is simply not there.
Besides, the only way you could pass a var without passing a type is to use either a generic TObject parameter, a generic type (D2008, as in ), or as an untyped parameter. I can't think of another way of passing it that would even compile.