Delphi 2009中的With处理方式

5

有人知道Delphi 2009在处理"with"时有什么不同吗?

昨天我通过将"with"拆解为完整的引用,例如"with Datamodule, Dataset, MainForm",成功解决了一个问题。 Delphi 2006及更早版本会将"Close"应用于Dataset,而Delphi 2009会将"Close"应用于MainForm并退出应用程序!


1
+1 这是一个精心设计的问题,可以引出一些真正优秀的答案! - Argalatyr
5个回答

16

没有任何改变。你之前的观察是错误的。在with语句中提到的对象被认为是“从右到左”的,所以在你的例子中,首先会搜索MainForm,然后是Dataset,最后是Datamodule。这一直都是这样的。这与你写下以下代码的效果相同:

with Datamodule do
  with Dataset do
    with MainForm do begin
      Close;
    end;

可以查看Delphi 2006文档;应该有一个名为声明和语句的部分,在其中您会找到关于结构化语句的内容,其中包括With语句的部分。

建议您不要使用with。它在调试期间和维护期间都会引起很多问题,维护甚至可能是由编写代码的人在前一天执行的。


嗯...我检查了2006年2月7日版本的单元和2009年6月2日版本,我确实添加了MainForm。所以在D2006中它并没有不同。 - user122603
那么应该使用什么替代方案呢?如果正在使用“with DBComponent.DataSource.DataSet do”,是否应该引入一个本地变量来保存引用? - Larry Lustig
1
是的,@Larry。例如:var dset: TDataset; dset := DBComponent.DataSource.Dataset; dset.foo; dset.bar; - Rob Kennedy
呃!对我来说是个大变化。嗯,好吧…… - Larry Lustig

11

With很危险。我不知道我需要说多少次,但显然我们还没有意识到这一点。

With只能“安全”地用于永远不会改变的对象。如果将其应用于您在自己的项目中定义的对象,则所有投注都无效,我敢说您应该只使用“if Random(50)<25”部分来执行代码,至少可以记录下奇怪的执行情况。

问题在于,一旦开始操作对象,引入新的方法或属性,或者重命名旧方法,所有现有的with语句使用那些方法都有可能改变含义。并且不是“警告:调用模糊方法”的更改。代码将只是执行先前不同的其他操作,而没有告诉您。

例如,假设您有以下内容:

with connection, file do
begin
    Close;
end;

那么你希望会发生什么?关闭文件是再自然不过的事情了,所以我期望文件会被关闭。让我们进一步假设,这个文件变量保存的是TSomeOddFile类型的对象,该对象没有定义Close方法,而是定义了CloseFile方法。那么上面的With语句将会关闭连接。

没问题,这已经有文档说明了。毕竟,没有人写这段代码时认为文件会被关闭,毕竟该对象的方法名就是CloseFile,只是我的假设是错误的,而我也不在这个项目中工作。但未来可能会加入该项目。

然后有人修复了这个问题,将CloseFile重命名为Close。上面的代码将悄无声息地开始关闭文件,而不是连接。没有警告,没有错误,编译后和之前一样运行良好。实际上并没有运行良好,等等,它根本不会运行良好。

所以,with语句会让你吃大亏。


1
有时候,意识到自己的不足只能通过经验来获得。+1 - skamradt
2
学习本来就是通过听取别人的经验教训来避免自己重蹈覆辙。WITH 让我浪费了很多时间,直到我发现它真的是一堆垃圾。 - Lasse V. Karlsen

3

使用with A,B,C,D是一种不好的做法,因为其他单元的更改可能会导致您的代码突然停止按预期工作。请参见此处获取更多信息,或者在此处搜索"with keyword"


3
编译器通常非常稳定,因此在排除其他所有可能性之前,请不要假设存在错误或更改。以下是一些我可以快速想到的原因:
1)查看是否使用了重载函数或运算符。由于 STRING(以及其他几种类型)的定义已更改,因此可能会选择不同的变量,因为签名实际上已更改。
2)还可能是某个已包含的单元现在定义了一个已经使用的标识符,并且优先于在另一个单元中公开的标识符。
如果没有,请逐步将代码隔离到最小示例中,尽可能少地使用单元。由于技巧在于行为更改时的最后一次更改是什么,因此请逐步进行。在此处发布该示例(或URL),这总是很有趣的。

+1 是为了实际回答问题,而不是重复说不应该使用 with 语句。 - Wouter van Nifterick

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接