德尔福是“与”吗? 关键字是不好的做法吗?
我一直在读有关 delphi 中 with 关键字的坏话,但在我看来,如果你不过度使用它。 它可以让你的代码看起来很简单。
我经常将所有 TClientDataSet 和 TField 放在 TDataModule 中。 因此,在我的表单中,我有这样的代码
procedure TMyForm.AddButtonClick(Sender: TObject);
begin
with LongNameDataModule do
begin
LongNameTable1.Insert;
LongNameTable1_Field1.Value := "some value";
LongNameTable1_Field2.Value := LongNameTable2_LongNameField1.Value;
LongNameTable1_Field3.Value := LongNameTable3_LongNameField1.Value;
LongNameTable1_Field4.Value := LongNameTable4_LongNameField1.Value;
LongNameTable1.Post;
end
end;
,没有 with 关键字,我必须编写这样的代码,
procedure TMyForm.AddButtonClick(Sender: TObject);
begin
LongNameDataModule.LongNameTable1.Insert;
LongNameDataModule.LongNameTable1_LongNameField1.Value := "some value";
LongNameDataModule.LongNameTable1_LongNameField2.Value :=
LongNameDataModule.LongNameTable2_LongNameField1.Value;
LongNameDataModule.LongNameTable1_LongNameField3.Value :=
LongNameDataModule.LongNameTable3_LongNameField1.Value;
LongNameDataModule.LongNameTable1_LongNameField4.Value :=
LongNameDataModule.LongNameTable4_LongNameField1.Value;
LongNameDataModule.LongNameTable1.Post;
end;
我认为使用 with 关键字更容易阅读。
我应该避免使用 with 关键字吗?
I been reading bad things about the with keyword in delphi but, in my opinion, if you don't over use it. It can make your code look simple.
I often put all my TClientDataSets and TFields in TDataModules. So in my forms I had code like this
procedure TMyForm.AddButtonClick(Sender: TObject);
begin
with LongNameDataModule do
begin
LongNameTable1.Insert;
LongNameTable1_Field1.Value := "some value";
LongNameTable1_Field2.Value := LongNameTable2_LongNameField1.Value;
LongNameTable1_Field3.Value := LongNameTable3_LongNameField1.Value;
LongNameTable1_Field4.Value := LongNameTable4_LongNameField1.Value;
LongNameTable1.Post;
end
end;
without the with keyword I have to write the code like this
procedure TMyForm.AddButtonClick(Sender: TObject);
begin
LongNameDataModule.LongNameTable1.Insert;
LongNameDataModule.LongNameTable1_LongNameField1.Value := "some value";
LongNameDataModule.LongNameTable1_LongNameField2.Value :=
LongNameDataModule.LongNameTable2_LongNameField1.Value;
LongNameDataModule.LongNameTable1_LongNameField3.Value :=
LongNameDataModule.LongNameTable3_LongNameField1.Value;
LongNameDataModule.LongNameTable1_LongNameField4.Value :=
LongNameDataModule.LongNameTable4_LongNameField1.Value;
LongNameDataModule.LongNameTable1.Post;
end;
I think is easier to read using the with keyword.
Should I avoid using the with keyword?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
除了像“with A、B、C、D”这样的病态条件之外,with 的最大危险是你的代码可以在不通知你的情况下悄悄改变含义。 考虑这个例子:
您编写此代码时知道 Bar 是 TFoo 的属性,而 Baz 是包含具有此代码的方法的类型的属性。
现在,两年后,一些善意的开发人员加入,为 TFoo 添加了 Baz 属性。 你的代码已经悄然改变了意义。 编译器不会抱怨,但代码现在已损坏。
The biggest danger of with, outside of pathological conditions like "with A, B, C, D" is that your code can silently change meaning with no notice to you. Consider this example:
You write this code knowing that Bar is a property of TFoo, and Baz is a property of the type containing the method which has this code.
Now, two years later, some well-meaning developer comes in adds a Baz property to TFoo. Your code has silently changed meaning. The compiler won't complain, but the code is now broken.
with 关键字是一个很好的功能,可以使代码更具可读性,但也存在一些缺陷。
调试:
当使用这样的代码时:
无法检查此类的属性,因此始终声明一个变量并使用with关键词。
接口:
在with子句中创建接口时,它会一直存在到方法的末尾:
清晰度
当在 with 子句中使用具有范围内已存在的属性或方法名称的类时,它很容易欺骗您。
当然,当名称重复时,您将使用 with 语句 (TMyForm) 中声明的类的属性和方法。
The with keyword is a nice feature for making your code more readable but there are some pitfalls.
Debugging:
When using code like this:
There is no way to inspect the properties of this class, so always declare a variable and use the with keyword on that.
Interfaces:
When creating an interface in the with clause it lives till the end of your method:
Clarity
When using a class in a with clause that has properties or method names that already exists within the scope, it can fool you easily.
Of course when having duplicate names, you're using the properties and methods of the class declared in your with statement (TMyForm).
with
语句有其用武之地,但我必须承认过度使用会导致代码不明确。 一个好的经验法则是确保添加 with 语句后代码“更”可读和可维护。 如果您觉得在添加语句后需要添加注释来解释代码,那么这可能是一个坏主意。 如果代码像您的示例中那样更具可读性,则使用它。顺便说一句:这一直是我在 Delphi 中最喜欢的显示模式窗口的模式之一
The
with
statement has its place but I have to agree that overuse can lead to ambiguous code. A good rule of thumb is to make sure the code is "more" readable and maintainable after adding the with statement. If you feel you need to add comments to explain the code after adding the statement then it is probably a bad idea. If the code is more readable as in your example then use it.btw: this was always one of my favorite patterns in Delphi for showing a modal window
我倾向于完全禁止 with 语句。 如前所述,它会使事情变得复杂,我的经验是它会的。 很多时候,调试器因为 withs 而需要计算值,而且我经常发现嵌套的 withs 会导致代码难以阅读。
Brian 的代码看起来可读且不错,但是如果您直接对发送者进行类型转换,则代码会更短,并且消除了对启用的该组件的所有疑问:
如果您担心输入太多,我会暂时参考长命名对象:
不过,我不明白为什么打字会打扰你。 我们首先是打字员,其次是程序员,以及代码完成、复制粘贴和按键记录可以帮助您成为一名更高效的打字员。
更新:
刚刚偶然发现了一篇长文章,其中有一小部分是关于 with 语句的: 他用关键字。 该语言中最丑陋、最危险、最令人震惊的功能。 :-)
I tend towards baning the with-statement altogether. As previously stated, it can make things complicated, and my experience is that it will. Many times the debugger want evaluate values because of withs, and all to often I find nested withs that lead to code that hard to read.
Brian's code seems readable and nice, but the code would be shorter if you just typecast the sender directly, and you remove all doubt about that component you enable:
If you are concerned about typing to much, I prefare to make a temporary referance to the long-named object:
I can't se why typing should bother you, though. We Are Typists First, Programmers Second, and code-completion, copy-paste and key-recording can help you be a more effective typist.
update:
Just stumbled over an long article with a little section on with-statements: he with keyword. The most hideous, dangerous, blow-your-own-feet-off feature in the language. :-)
当我第一次开始 Pascal 编程(使用 TurboPascal!)并边学边学时,WITH 看起来很棒。 正如你所说,这是繁琐打字的答案,也是那些长记录的理想选择。 自从 Delphi 出现以来,我一直在删除它并鼓励其他人放弃它 - Verity 在 注册
除了可读性降低之外,我避免使用它还有两个主要原因:
也就是说,为了可读性,我仍然使用语法:
我还没有看到更好的构造。
When I first began pascal programming (with TurboPascal!) and learnt as I went, WITH seemed wonderful. As you say, the answer to tedious typing and ideal for those long records. Since Delphi arrived, I've been removing it and encouraging other to drop it - neatly summed-up by Verity at the register
Apart from a reduction in readability there are two main reasons why I'd avoid it:
That said, for readability I still use the syntax:
I've not seen a better construct.
在我看来,您的示例(通过单击按钮访问数据模块)是一个设计不当的示例。 如果您将此代码移至数据模块应有的位置,则对WITH 的全部需求就消失了。 OnClick 然后只调用 LongNameDataModule.InsertStuff 并且不需要。
With 是一个很差的设备,您应该查看代码以了解为什么需要它。 您可能做错了什么,或者可以采取更好的方法。
Your example, of a datamodule access within a button click, is a poorly contrived example in my opinion. The whole need for WITH goes away if you move this code into the data module where it should be. The OnClick then just calls LongNameDataModule.InsertStuff and there is no with needed.
With is a poor device, and you should look at your code to see why you are needing it. You probably did something wrong, or could do it a better way.
正如 Vegar 提到的,使用临时引用同样简洁、更具可读性、更容易调试,并且不太容易出现隐秘问题。
到目前为止,我从未发现需要使用with。 我曾经对此很矛盾,直到我接手了一个经常使用思维扭曲双重的项目。 质疑原始开发人员是否打算引用第一个 with 或第二个中的项目,如果该模糊引用是 with-slip 或笨拙的代码,则尝试调试它是一种痛苦,并且扩展或修改使用这些令人厌恶的类的连锁反应是不值得任何人花时间的。
显式代码简单更具可读性。 这样你就可以吃到蛋糕并享受吃的乐趣了。
As Vegar mentioned, it's just as neat and much more readable, easier to debug, and less prone to stealth issues to use a temporary reference.
So far, I have never found a need to use with. I used to be ambivalent over it, until I took over a project that used the mind bending double with frequently. Questioning whether the original developer intended to reference items in the first with or second, if that ambiguous reference was a with-slip or clumsy code, the torment of trying to debug it, and the knock on effects of extending or modifying classes that use these abominations is just not worth anyone's time.
Explicit code is simply more readable. This way you can have your cake and enjoy eating it.
我坚信在 Delphi 中删除WITH 支持。 您使用带有命名字段的数据模块的示例用法大约是我能看到它工作的唯一实例。 除此之外,反对它的最佳论据是克雷格·斯图茨(Craig Stuntz)提出的——我投了赞成票。
我只是想指出,随着时间的推移,您可能最终(应该)删除 OnClick 事件中的所有编码,并且您的代码最终也将从数据模块上的命名字段迁移到使用包装此数据的类,并且使用 WITH 的原因将消失。
I'm a firm believer of removing WITH support in Delphi. Your example usage of using a datamodule with named fields is about the only instance I could see it working out. Otherwise the best argument against it was given by Craig Stuntz - which I voted up.
I just like to point out that over time you may eventually (should) rmeove all coding in OnClick events and your code will also eventually migrate away from named fields on datamodules into using classes that wrap this data and the reason to use WITH will go away.
你的问题是“锤子并不总是解决方案”的一个很好的例子。
在这种情况下,“with”不是您的解决方案:您应该将此业务逻辑从表单移至数据模块中。
不这样做违反了德米特法则,就像mghie(Michael Hieke)已发表评论。
也许您的示例只是说明性的,但如果您实际上在项目中使用类似的代码,那么您应该这样做:
然后从您的表单中调用它,如下所示:
这有效地摆脱了您的 with 语句,并使同时你的代码更易于维护。
当然,用单引号包围 Delphi 字符串也将有助于编译;-)
Your question is an excellent example of 'a hammer is not always the solution'.
In this case, 'with' is not your solution: You should move this business logic out of your form into your datamodule.
Not doing so violates Law of Demeter like mghie (Michael Hieke) already commented.
Maybe your example was just illustrative, but if you are actually using code like that in your projects, this is what you should do in stead:
And then call it from your form like this:
This effectively gets rid of your with statement, and makes your code more maintainable at the same time.
Of course surrounding Delphi strings with single quotes will help making it compile as well ;-)
“with”的主要问题是您不知道它的范围在哪里结束,并且您可能有多个重叠的 with 语句。
我认为只要您的代码可读,您就不应该避免使用它。
使其更具可读性(并且在较长的代码中减少混乱)的建议之一是,如果 codegear 添加 选项 以允许在 with 中使用别名,并且可能允许在一个中使用多个 with:
The main problem with "with" is that you don't know where its scope ends, and you could have multiple overlapping with statements.
I don't think you should avoid using it, as long as your code is readable.
One of the proposals to make it more readable (and less confusing in longer code) was if codegear added the option to allow for aliases in with, and probably allowing multiple withs in one:
就我而言,在你给出的情况下,With 是完全可以接受的。 它确实提高了代码的清晰度。
真正的邪恶是当你同时打开多个 with 时。
另外,我的观点是,您使用的 with on 会产生很大的差异。 如果它是一个真正不同的对象,那么 with 可能是一个坏主意。 然而,我不喜欢在一个级别上有很多变量,即使这是有意义的——通常是保存整个非常复杂的数据项的数据对象——通常是程序设计用来处理的整个工作。 (我认为这种情况不会发生在没有此类项目的应用程序中。)为了让世界更清晰,我经常使用记录对相关项目进行分组。 我发现我使用的几乎所有 with 都是为了访问此类子组。
As far as I'm concerned, With is quite acceptable in the case you give. It certainly improves the code clarity.
The real evil is when you have multiple with's open at once.
Also, my opinion is that what you are using the with on makes a big difference. If it's a truly different object then the with is probably a bad idea. However, I dislike having a lot of variables at one level even when this makes sense--generally data objects that hold an entire very complex data item--generally the entire piece of work the program is designed to work with. (I do not think this case would occur in an app that didn't have such an item.) To make the world clearer I often use records to group related items. I find that almost all withs I use are for accessing such subgroups.
关于为什么 with 语句不好,这里有很多很好的答案,所以我尽量不重复它们。 我多年来一直使用 with 语句,但现在我开始回避它。 部分原因是确定范围可能很困难,但我最近开始进行重构,并且没有一个自动重构可以与 with 语句一起使用 - 而且自动重构非常棒。
另外,前段时间我制作了一个视频,解释为什么 with 语句不好,它不是我最好的作品之一,但 这里
There are many excelent answers here as to why the with statement is bad, so I'll try not to repeat them. I've been using the with statement for years and I'm very much starting to shy away from it. This is partially beause it can be difficult to work out scope, but I've been starting to get into refactoring lately, and none of the automated refactorings work withing a with statement - and automated refactoring is awesome.
Also some time ago I made a video on why the with statement is bad, it's not one of my best works but Here it is
仅临时使用
with
(就像您临时注释掉一样)。它可以帮助您编写代码草图以快速编译和运行某些内容。 如果合并解决方案,请将其清理干净! 当您将代码移动到正确的位置时,删除
with
。Use
with
only temporarily (just as you comment-out temporarily).It helps you write code sketches to get something compiled and running fast. If you consolidate the solution, clean it up! Remove
with
as you move code to the right place.当前的 With 语句是“危险的”,但它可以得到实质性改进:
我的建议是:
到同上标记:http://en.wikipedia.org/wiki/Ditto_mark)。
The current With statement is "dangerous", but it can be substantially improved:
My proposal is:
to the ditto mark: http://en.wikipedia.org/wiki/Ditto_mark).