在我帮助维护的代码中,我找到了多个代码示例:
Description := IfThen(Assigned(Widget), Widget.Description, 'No Widget');
我预计当Widget为零时会崩溃,但是当我测试它时,它运行得很好。
如果我在Project - Options - Compiler中关闭“Code inlining control”重新编译它,我会收到访问冲突。
似乎,因为IfThen被标记为内联,如果Widget为nil,编译器通常不会评估Widget.Description。
是否有任何理由认为代码应该“固定”,因为它似乎没有被破坏?他们不希望代码不必要地改变。 是否有可能咬他们?
我已经使用Delphi XE2和XE6进行了测试。
答案 0 :(得分:7)
就个人而言,我讨厌依赖一种不合同的行为。
The inline directive is a suggestion to the compiler.
如果我正确理解了我读到的内容,那么如果使用运行时包构建代码,代码也会崩溃。
内联不会跨包边界发生
就像Uli Gerhardt评论的那样,它可能被认为是一个错误,它首先起作用。由于行为不是契约性的,它可以随时改变。
如果我要提出任何建议,我会将其标记为低优先级"修复"。我很确定有人会争辩说,如果代码有效,它不需要修复,没有错误。那时,它变得更像一个哲学问题(If a tree falls in a forest and no one is around to hear it, does it make a sound?)
答案 1 :(得分:5)
是否有任何理由认为代码应该被修复",因为它似乎没有被破坏?
这真的是一个只有你能回答的问题。但是,要回答它,您需要充分了解依赖此行为的含义。我认为有两个主要问题:
要扩展第2点,请考虑您问题中的陈述:
Description := IfThen(Assigned(Widget), Widget.Description, 'No Widget');
现在,如果Widget.Description
是一个字段,或者是一个具有读取字段的getter的属性,则编译器会确定评估没有副作用。可以安全地跳过此评估。
另一方面,如果Widget.Description
是函数或具有getter函数的属性,则编译器确定可能存在副作用。因此,它确保Widget.Description
只被评估一次。
因此,掌握了这些知识,以下几种方法可以使您的代码失败:
Description
属性getter从字段getter更改为函数getter。如果是我,我不想依赖这种行为。但正如我在顶部说的那样,最终是你的决定。
最后,行为已从XE7更改。内联函数的所有参数都只计算一次。这与其他语言保持一致,这意味着可观察行为不再受内联决策的影响。我认为XE7中的更改是一个bug修复。
答案 2 :(得分:4)
它已经被修复 - 在XE7中并确认这应该是错误的行为。