怎么知道什么类型是var? [英] How to know what type is a var?

查看:282
本文介绍了怎么知道什么类型是var?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

此代码返回:

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

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

I know a non instantiated var is only a pointer address. At compile time, the compiler parses and do the type safety check.

在运行时,有没有什么方法可以更多地了解一个var,只传递其地址?

推荐答案

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.

指针在编译时只有一个类型。在运行时,可以对该地址进行的所有操作都已经确定。您已经注意到,编译器会检查它。在运行时检查变量的类型仅在变量的类型可能会更改的语言(如动态语言)中有用。最接近的Delphi来自于它的 Variant 类型。变量的类型始终为 Variant ,但您可以在其中存储许多类型的值。要找出它的含义,您可以使用 VarType 函数。

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 always Variant, but you can store many types of values in it. To find out what it holds, you can use the VarType function.

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

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 to TypeInfo.

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

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 call New on a pointer variable, the compiler inserts an additional parameter that holds the PTypeInfo value for the type you're allocating. When you call SetLength on a dynamic array, the compiler inserts a PTypeInfo value for the array type.

The你给出的答案表明你正在寻找除了你所要求的以外的东西。给你的问题,我以为你在找一个可以满足这个代码的假设函数:

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:

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 IsObject 函数从JCL 构建该函数:

Let's use the IsClass and IsObject functions from the JCL to build that function:

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;

显然对于 S 实例,但是看看 Obj 会发生什么:

It obviously won't work for S or Instance above, but let's see what happens with Obj:

Info := GetVariableTypeInfo(@Obj);

应该给出访问冲突。 Obj 没有价值,所以 IsClass IsObject 正在读取未指定的内存地址,可能不是属于您的进程的内存地址。您要求使用变量的地址作为其输入的例程,但仅仅是地址是不够的。

That should give an access violation. Obj has no value, so IsClass and IsObject 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.

现在让我们仔细看看如何 IsClass IsObject 真的表现得很好。这些函数具有任意值,并检查值是否类似于,它可能是给定类型的值,即对象(实例)或类。使用它像这样:

Now let's take a closer look at how IsClass and IsObject 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:

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

请注意,这些函数告诉你没有关于变量的,只有关于 他们持有。我不会真正考虑这些功能,然后回答如何获取有关变量的类型信息的问题。

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:

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;

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

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.

这篇关于怎么知道什么类型是var?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆