当前位置:  开发笔记 > 编程语言 > 正文

如何知道var是什么类型的?

如何解决《如何知道var是什么类型的?》经验,为你挑选了1个好方法。

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

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,只传递其地址?



1> Rob Kennedy..:

没有.

首先,没有"非实例变量"这样的东西.只需在源文件中键入其名称和类型即可实例化它.

其次,通过在源代码中查看变量,您已经知道所有关于变量的知识.编译程序后,变量不再存在.在那之后,它只是位.

指针在编译时只有一个类型.在运行时,已经确定了可以对该地址执行的所有操作.正如您已经指出的那样,编译器会检查它.在运行时检查变量的类型仅在变量类型可能更改的语言中有用,如在动态语言中.最接近Delphi的是它的Variant类型.变量的类型始终是Variant,但您可以在其中存储许多类型的值.要了解它的含义,您可以使用该VarType功能.

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

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

您给出的答案表明您正在寻找除您要求之外的其他内容.鉴于您的问题,我认为您正在寻找一个可以满足此代码的假设函数:

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;

让我们使用JCL中的IsClassIsObject函数来构建该函数:

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没有价值,所以IsClassIsObject两者都将被读取未指定的内存地址,可能不是一个属于你的进程.您要求使用变量的地址作为输入的例程,但仅仅是地址是不够的.

现在让我们仔细看看如何IsClass以及IsObject真正的行为.这些函数采用任意值并检查值是否看起来可能是给定类型的值,无论是对象(实例)还是类.像这样使用它:

// 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;

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

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

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有