Delphi 铸造与 as 和 Supports 的区别

Posted

技术标签:

【中文标题】Delphi 铸造与 as 和 Supports 的区别【英文标题】:Delphi casting with as and Supports difference 【发布时间】:2021-06-17 02:08:04 【问题描述】:

使用Supportsas 关键字进行转换有什么区别,除了as 之外,我首先需要检查是否可以使用is 关键字进行转换。

【问题讨论】:

【参考方案1】:

Supports 将提供一个接口(如果该接口受支持)。

is 确定一个类/接口是否派生自另一个类/接口。

asis 做同样的事情,但也返回一个经过类型检查的强制转换。

如果你已经用is确认了施法成功,就不用as,直接施法就行了,效率更高:

if(pSomeObjectRef is TMyObject) then
  TMyObject(pSomeObjectRef).MyUsefulMethod(...);

由于 Delphi 不支持多重继承,使用接口是实现这种行为的唯一方法。一个对象可以是多个事物,而不仅仅是它自己或它的祖先。

如果您不使用接口,则不需要使用Supports()

使用as 进行转换允许您将对象引用转换为接口,以及对不同类对象的引用。就个人而言,我不使用as,而且我很少在我正在查看的代码中看到它。由于as 可以引发异常,因此您应该采取措施避免异常,并在引发异常时捕获它们。无论如何你都可以检查这些,所以永远不需要使用as

当转换到一个接口时,你可以使用Supports()的结果,而不是依赖异常来捕获接口不存在的情况:

if (SysUtils.Supports(pSomeObjectRef, IMyWantedInterface, diInterfaceRef)) then
begin
  diInterfaceRef._AddRef();   // removed when diInterface falls out of scope
  ...
end
else
begin  // it doesn't support the interface!
  ...
end;

您是要捕获异常(有些人喜欢,有些人不喜欢 - 它确实使代码的线性度降低)还是 if..else 的代码,通常是一个偏好问题。我宁愿不依赖异常(但我仍然有try..finallytry..except 块),但当然还有其他意见!

【讨论】:

那么我什么时候应该使用“as”? 当对象不支持接口时程序无法运行时使用。否则使用支持。 我看到大卫在我更新答案时与您分享了他的智慧...... 您不应该在Supports() 返回的接口上手动调用_AddRef()。当Supports() 退出时,它的引用计数已经增加了。手动调用_AddRef() 需要手动_Release() 以避免泄漏。

以上是关于Delphi 铸造与 as 和 Supports 的区别的主要内容,如果未能解决你的问题,请参考以下文章

为啥铸造给CS0030,而“as”有效?

Widget only supports Widgets as children

锻造与铸造的区别

Delphi 中的 FloatToStr(Now) 和 SQL Server 中的 Cast(GETDATE() as float) 之间的区别

铸造跟CNC哪种好?为啥?

delphi 如何保留小数