如何安全地绕过Delphi错误:“形式和实际参数的类型必须相同” [英] how to safely bypass Delphi Error: "types of formal and actual parameters must be identical"

查看:125
本文介绍了如何安全地绕过Delphi错误:“形式和实际参数的类型必须相同”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我第一次尝试声明一个对象类型或其任何后代。 b
$ b

  procedure TotalDestroy(var obj:TMyObject); 

但使用后代对象时

 类型TMyNewerObject = class(TMyObject); 
var someNewerObject:TMyNewerObject;

TotalDestroy(someNewerObject);

我得到臭名昭着的错误正式和实际参数的类型必须相同



所以,尽管找到一个解决方案,我看了Delphi系统的源代码 FreeAndNil 程序。而且我发现这个很棒的声明,以及这个令人惊讶的评论

  {FreeAndNil释放给定的TObject实例和
设置变量引用为零。
注意只传递TObjects到这个例程。 }

程序FreeAndNil(var Obj);

它避免了类型检查错误,但它不使用安全网。



我的问题是...有没有任何安全的方法来检查无类型的var参数的类型?



或者换句话说,你可以改进这个Delphi的源代码,以便不需要警告吗?

 程序FreeAndNil(var Obj); 
var
Temp:TObject;
begin
Temp:= TObject(Obj);
指针(Obj):= nil;
Temp.Free;
结束


解决方案

非常类似于 Lasse's





除非您正在编写一个赋值语句来更改输入参数本身的值,而不仅仅是其属性之一,否则不应该通过引用传递参数第一个。



如果您正在编写一个赋值语句来更改参数的值,那么编译器消息真的是真的,你应该注意它。



需要绕过错误的一个原因是当你写一个功能像 TApplication.CreateForm 其作用是更改输入参数的值,新值的类型不同,编译时无法确定。如果您正在撰写此类功能,那么您唯一可以使用Delphi的选项就是使用 无类型的var 参数,然后调用者和接收方都有额外的负担,以确保一切顺利。调用者需要确保它传递一个变量,该变量能够保存该函数将放入其中的任何类型的值,并且该函数需要确保它存储与调用方所请求的类型兼容的值。



CreateForm 的情况下,调用者传入类引用文字和该类类型的变量。该函数实例化该类并将该参考存储在该变量中。



我不认为 CreateForm FreeAndNil ,主要是因为他们的无类型参数牺牲类型安全的方式作为回报相对较少的额外方便。您没有显示您的 TotalDestroy 函数的实现,但我怀疑其var参数最终将提供与其他两个函数相同的低效用。看到我的文章:




I need a way to write a generic procedure to act upon an object type or any of its descendants.

My first attempt was to declare

procedure TotalDestroy(var obj:TMyObject);

but when using it with a descendant object

type TMyNewerObject = class(TMyObject);
var someNewerObject: TMyNewerObject;

TotalDestroy(someNewerObject);

I get the infamous error "types of formal and actual parameters must be identical"

So, while strugling to find a solution, I looked at the source code of Delphi system FreeAndNil procedure. And I found this awesome declaration, along with this astonishing comment

{ FreeAndNil frees the given TObject instance and 
  sets the variable reference to nil.  
  Be careful to only pass TObjects to this routine. }

procedure FreeAndNil(var Obj);

It avoids the type checking error, but it uses no safety net.

My question is ... is there any safe way to check the type of an untyped var parameter?

or in other words, can you improve this Delphi source code so that the warning would not be needed?

procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;

解决方案

I've written about this before, using an example very similar to Lasse's:

Unless you're writing an assignment statement to change the value of the input parameter itself, and not just one of its properties, you shouldn't pass a parameter by reference in the first place.

If you are writing an assignment statement to change the parameter's value, then the compiler message really is true, and you should heed it.

One reason for needing to by-pass the error is when you're writing a function like TApplication.CreateForm. Its job is to change the input parameter's value, and the type of the new value varies and cannot be determined at compile time. If you're writing such a function, then your only option with Delphi is to use an untyped var parameter, and then there is extra burden on both the caller and the receiver to make sure everything goes right. The caller needs to make sure it passes a variable that is capable of holding values of whatever type the function will put in it, and the function needs to make sure it stores a value of a type compatible with what the caller requested.

In the case of CreateForm, the caller passes in a class-reference literal and a variable of that class type. The function instantiates the class and stores the reference in the variable.

I don't think very highly of either CreateForm or FreeAndNil, largely because of the way their untyped parameters sacrifice type safety in return for comparatively little extra convenience. You haven't shown the implementation of your TotalDestroy function, but I suspect its var parameter will ultimately provide the same low utility as in those other two functions. See my articles on both:

这篇关于如何安全地绕过Delphi错误:“形式和实际参数的类型必须相同”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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