gpt4 book ai didi

delphi - 如何知道什么是 var 类型?

转载 作者:行者123 更新时间:2023-12-03 14:40:42 25 4
gpt4 key购买 nike

TypeInfo(Type) 返回指定类型的信息,有没有办法知道 var 的类型信息?

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

此代码返回:

[DCC 错误] Unit1.pas(354): E2133 TYPEINFO 标准函数需要类型标识符

我知道非实例化的 var 只是一个指针地址。
在编译时,编译器解析并进行类型安全检查。

在运行时,有什么方法可以了解更多关于 var 的信息,只传递它的地址?

最佳答案

不。

首先,没有“非实例化变量”之类的东西。您只需键入其名称并将其键入源文件即可实例化它。

其次,通过在源代码中查看变量,您已经了解了有关变量的所有信息。编译程序后,该变量将不复存在。在那之后,一切都只是一点点。

指针仅在编译时具有类型。在运行时,可以对该地址执行的所有操作都已确定。正如您已经指出的那样,编译器会对此进行检查。在运行时检查变量的类型仅在变量类型可能改变的语言中有用,例如在动态语言中。最接近德尔福的是它的Variant。类型。变量的类型始终为 Variant ,但您可以在其中存储多种类型的值。要了解它的内容,您可以使用 VarType功能。

您可以随时使用 TypeInfo获取变量关联类型的类型信息,也可以直接命名自己感兴趣的类型;如果变量在范围内,那么您可以找到它的声明并在调用 TypeInfo 时使用声明的类型.

如果您想将任意地址传递给函数并让该函数自己发现类型信息,那么您就不走运了。您将需要传递 PTypeInfo值作为附加参数。这就是所有内置的 Delphi 函数所做的。例如,当您调用 New在指针变量上,编译器插入一个附加参数,该参数包含 PTypeInfo您分配的类型的值。当您调用 SetLength在动态数组上,编译器插入 PTypeInfo数组类型的值。

The answer that you gave表明您正在寻找与您所要求的不同的东西。鉴于您的问题,我认为您正在寻找一个可以满足此代码的假设函数:

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;

让我们使用 IsClass and IsObject functions from the JCL构建该功能:
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;

它显然不适用于 SInstance上面,但让我们看看 Obj 会发生什么:
Info := GetVariableTypeInfo(@Obj);

这应该会导致访问冲突。 Obj没有值(value),所以 IsClassIsObject两者都将读取一个未指定的内存地址,可能不属于您的进程。您要求一个使用变量地址作为输入的例程,但仅仅地址是不够的。

现在让我们仔细看看 IsClassIsObject真正的表现。这些函数采用任意值并检查该值是否看起来可能是给定类型的值,无论是对象(实例)还是类。像这样使用它:
// 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;

请注意,这些函数不会告诉您有关变量的任何信息,而只会告诉您它们所持有的值。那么,我不会真正考虑这些函数来回答如何获取有关变量的类型信息的问题。

此外,您说您对变量的所有了解都是它的地址。您找到的函数不采用变量的地址。它们取变量的值。这是一个演示:
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;

您可能会反对我通过将明显是垃圾的东西传递给它们来滥用这些功能。但我认为这是谈论这个话题的唯一方式。如果你知道你永远不会有垃圾值,那么你无论如何都不需要你要求的函数,因为你已经对你的程序有足够的了解,可以为你的变量使用真正的类型。

总的来说,你问错了问题。 不是询问您如何确定变量的类型或内存中值的类型。您应该问自己是如何进入不知道变量和数据类型的位置的 .

关于delphi - 如何知道什么是 var 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/554100/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com