在我帮助维护的代码中,我发现了多个示例代码,如下所示:
Description := IfThen(Assigned(Widget), Widget.Description, 'No Widget');
Run Code Online (Sandbox Code Playgroud)
我希望当Widget为零时会崩溃,但是当我对其进行测试时,它运行良好。
如果我在“项目”-“选项”-“编译器”中关闭了“代码内联控件”,则重新编译它,则会出现访问冲突。
似乎因为IfIfn被标记为内联,所以如果Widget为nil,则编译器通常不会评估Widget.Description。
有什么理由应该对代码进行“修复”,因为它似乎没有被破坏?他们不想不必要地更改代码。可能会咬他们吗?
我已经用Delphi XE2和XE6对其进行了测试。
就个人而言,我讨厌依赖于非契约行为。
如果我正确理解所读内容,则使用运行时程序包进行构建时,代码也会崩溃。
内联永远不会跨越包边界发生
就像乌利·格哈特(Uli Gerhardt)所评论的那样,它首先可以被认为是一个臭虫。由于行为不是契约性的,因此可以随时更改。
如果我有任何建议,我将其标记为低优先级“修复”。我敢肯定,有人会争辩说,如果代码有效,则不需要修复,就不会有bug。在那一点上,它更多地是一个哲学问题(如果一棵树掉在森林里,没人在周围听到它,它会发出声音吗?)
有什么理由应该对代码进行“修复”,因为它似乎没有被破坏?
这确实是一个只有您才能回答的问题。但是,要回答这个问题,您需要充分理解依赖这种行为的含义。我认为有两个主要问题:
为了扩展第二点,请考虑您的问题中的陈述:
Description := IfThen(Assigned(Widget), Widget.Description, 'No Widget');
Run Code Online (Sandbox Code Playgroud)
现在,如果Widget.Description是字段,或者是具有读取字段的getter的属性,则编译器会确定评估没有副作用。可以安全地跳过此评估。
另一方面,如果Widget.Description是函数或具有getter函数的属性,则编译器确定可能存在副作用。因此,它确保只对它Widget.Description进行一次评估。
因此,有了这些知识,您可以通过以下几种方法使代码失败:
Description属性获取器从字段获取器更改为函数获取器。如果是我,我不想依靠这种行为。但是正如我在最上面说的那样,最终由您决定。
最后,行为已从XE7更改。内联函数的所有参数仅计算一次。这与其他语言保持一致,这意味着可观察的行为不再受内联决策的影响。我将XE7中的更改视为错误修复。
| 归档时间: |
|
| 查看次数: |
322 次 |
| 最近记录: |