VB.NET“与” 声明——拥抱还是避免?
在工作中,我经常从事一些项目,其中某些对象的许多属性必须在其构建过程中或在其生命周期的早期进行设置。 为了方便和可读性,我经常使用 With
语句来设置这些属性。 我发现这
With Me.Elements
.PropertyA = True
.PropertyB = "Inactive"
' And so on for several more lines
End With
看起来要好得多
Me.Elements.PropertyA = True
Me.Elements.PropertyB = "Inactive"
' And so on for several more lines
比简单设置属性的很长的语句
。 我注意到在调试时使用 With
存在一些问题; 但是,我想知道是否有任何令人信服的理由在实践中避免使用 With
? 我一直认为通过编译器为上述两种情况生成的代码基本上是相同的,这就是为什么我总是选择编写我认为更具可读性的代码。
At work, I'm frequently working on projects where numerous properties of certain objects have to be set during their construction or early during their lifetime. For the sake of convenience and readability, I often use the With
statement to set these properties. I find that
With Me.Elements
.PropertyA = True
.PropertyB = "Inactive"
' And so on for several more lines
End With
Looks much better than
Me.Elements.PropertyA = True
Me.Elements.PropertyB = "Inactive"
' And so on for several more lines
for very long statements that simply set properties.
I've noticed that there are some issues with using With
while debugging; however, I was wondering if there were any compelling reasons to avoid using With
in practice? I've always assumed the code generated via the compiler for the above two cases is basically the same which is why I've always chosen to write what I feel to be more readable.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
如果你有很长的变量名并且最终会是:
那么我会使用WITH来使其更具可读性:
在后面的示例中,甚至比第一个示例具有性能优势,因为在第一个示例中,我每次访问用户时都会获取用户属性,在WITH-情况下我只获取用户一次。
我可以在不使用 with 的情况下获得性能增益,如下所示:
但我会选择使用 WITH 语句,它看起来更干净。
我只是以此为例,所以不要抱怨有很多关键字的类,另一个例子可能是这样的:WITH RefundDialog.RefundDatagridView.SelectedRows(0)
If you have long variablenames and would end up with:
then I would use WITH to make it more readable:
In the later example there are even performance benefit over the first example because in the first example Im fetching the user every time I access a user property and in the WITH-case I only fetch the user one time.
I can get the performance gain without using with, like this:
But I would go for the WITH statement instead, it looks cleaner.
And I just took this as an example so dont complain over a class with many keywords, another example could be like: WITH RefundDialog.RefundDatagridView.SelectedRows(0)
在实践中,并没有真正令人信服的理由反对它。 我不是粉丝,但这是个人偏好,没有经验数据表明
With
构造不好。在 .NET 中,它编译为与完全限定对象名称完全相同的代码,因此这种糖不会造成性能损失。 我通过编译然后反汇编以下 VB .NET 2.0 类来确定这一点:
反汇编如下 - 请注意,对
sb2
的Append
方法的调用看起来相同With
语句调用sb
:因此,如果您喜欢它,并且发现它更具可读性,那就去吧; 没有令人信服的理由不这样做。
(顺便说一句,Tom,我有兴趣知道调试器发生了什么——我不记得了基于
With
语句在调试器中看到任何异常行为,所以我很想知道您确实看到了什么行为。)In practice, there are no really compelling points against it. I'm not a fan, but that's a personal preference, there's no empirical data to suggest that the
With
construct is bad.In .NET, it compiles to exactly the same code as fully-qualifying the object name, so there is no performance penalty for this sugar. I ascertained this by compiling, then disassembling, the following VB .NET 2.0 class:
The disassembly is as follows -- note that the calls to
sb2
'sAppend
method look identical to theWith
statement calls forsb
:So if you like it, and find it more readable, go for it; there's no compelling reason not to.
(By the way, Tom, I'm interested in knowing what happened with the debugger -- I can't recall ever seeing any unusual behavior in the debugger based on a
With
statement, so I'm curious to know what behavior you did see.)使用 With 和重复引用对象之间存在差异,这一点很微妙,但我认为应该牢记在心。
当使用WITH语句时,它会创建一个引用该对象的新局部变量。 使用 .xx 的后续引用是对该本地引用的属性的引用。 如果在WITH语句执行过程中,原变量引用发生改变,则WITH引用的对象不会改变。 考虑一下:
因此,WITH 语句不仅仅是语法糖,它确实是一个不同的结构。 虽然您不太可能编写像上面这样的显式代码,但在某些情况下,这可能会无意中发生,因此您应该意识到这个问题。 最可能的情况是您可能正在遍历一个结构,例如对象网络,其互连可以通过设置属性隐式更改。
There is a difference between using With and making repeating references to an object, which is subtle but should be borne in mind, I think.
When a WITH statement is used, it creates a new local variable referencing the object. Subsequent references using .xx are references to properties of that local reference. If during the execution of the WITH statement, the original variable reference is changed, the object referenced by the WITH does not change. Consider:
So, the WITH statement is not simply syntactical sugar, it is genuinely a different construct. Whilst you would be unlikely to code something explicit like the above, in some situations this might occur inadvertently so you should be aware of the issue. The most likely situation is where you may be traversing a structure such as a network of objects whose interconnections my be implicitly changed by setting properties.
这一切都与可读性有关。 像所有语法糖一样,它可能会被过度使用。
拥抱它,如果您要在几行中设置对象的多个成员
避免使用“With”做任何其他事情
如果您编写一个跨越 50-100 行的 With 块并且涉及许多其他变量,这使得记住在块顶部声明的内容真的很困难。 出于显而易见的原因,我不会提供这种混乱代码的示例
It's all about readability. Like all syntactic sugar, it can be overused.
Embrace it IF you're setting several members of an object over a few lines
Avoid doing anything else with "With"
If you write a With block that spans 50-100 lines and involves lots of other variables it can make it REALLY difficult to remember what was declared at the top of the block. For obvious reasons, I won't provide an example of such messy code
如果它确实使代码更具可读性,那就去做吧。 如果它导致可读性降低,请避免使用 - 特别是,我建议您避免嵌套 With 语句。
C# 3.0 具有专门用于对象初始化的此功能:
这不仅是 LINQ 所必需的,而且在语法不指示代码异味的情况下也是有意义的。 我通常发现,当我在一个对象上执行超出其初始构造的许多不同操作时,这些操作应该封装为对象本身的单个操作。
关于你的例子的一点说明——你真的需要“我”吗? 为什么不直接写:
? 在这种情况下肯定暗示着“我”......
Where it makes the code genuinely more readable, go for it. Where it makes it less readable, avoid it - in particular, I suggest you avoid nesting With statements.
C# 3.0 has this feature solely for object initialization:
This is not only pretty much required for LINQ, but it also makes sense in terms of where the syntax doesn't indicate a code smell. I usually find that when I'm performing many different operations on an object beyond its initial construction, those operations should be encapsulated as a single one on the object itself.
One note about your example - do you really need the "Me" at all? Why not just write:
? Surely "Me" is implied in that case...
我会对大量使用 this 关键字的代码表示怀疑:如果它用于更容易设置大量实例变量或属性,我认为这可能表明您的类太大( 大类气味)。 如果你用它来替换像这样的长链调用:
那么你可能违反了 Demeter法律
I would be suspicious of code that uses a lot this keyword: if it is used to make easier to set lots of instance variables or properties I think this may indicate that your classes are too large ( Large Class smell ). If you use it to replace long chains of calls like this:
then you are probably violating Demeter Law
我不使用 VB.NET(我曾经使用纯 VB)但是...
前导点是强制性的吗? 如果是这样,那么我认为没有问题。 在 Javascript 中,使用
with
的结果是对象的属性看起来与普通变量一样,这是非常危险的,因为你看不到如果您要访问属性或变量,则应避免使用with
。它的使用不仅在视觉上更容易,而且对于重复访问对象的属性来说,它可能会更快,因为对象仅通过方法链获取一次,而不是每个属性都获取一次。
我确实同意其他回复,即您应该避免嵌套使用
with
,其原因与为什么在 Javascript 中完全避免with
的原因相同:因为您不再看到什么对象你的财产属于。I don't use VB.NET (I used to use plain VB) but...
Is the leading dot mandatory? If so, then I don't see a problem. In Javascript, the result of using
with
is that a property of an object looks just the same as a plain variable, and that is very dangerous, as you don't see if you're accessing a property or a variable, and thus,with
is something to avoid.Not only is its use easier on the eyes, but for repeated access to properties of an object, it's likely to be faster, as the object is fetched through the method chain only once, and not once for every property.
I do agree with other replies that you ought to avoid nested use of
with
, for the same reason as why to avoidwith
altogether in Javascript: because you no longer see what object your property belongs to.“with”基本上是来自 Smalltalk 的“cascade”。 它是 Kent Beck 的 Smalltalk 最佳实践模式书中的一个模式。
该模式的摘要:当对发送到对象的消息进行分组有意义时使用它。 如果恰好是发送到同一对象的一些消息,请不要使用它。
The 'with' is basically the 'cascade' from Smalltalk. It is a pattern in Kent Beck's Smalltalk Best Practice Patterns book.
A summary of the pattern: use it when it makes sense to group the messages sent to the object. Don't use it if it just happens to be some messages sent to the same object.
不惜一切代价避免使用WITH块(甚至是可读性)。 有两个原因:
为了描述这一点,我们有一个来自教科书的(损坏的)示例,我的同事必须向作者询问(这确实不正确,名称已被更改以保护......无论如何):
OrderBy 和 ThenBy 根本没有效果。 如果您通过仅删除 With 和 End With 来重新格式化代码,并在前三行的末尾添加行继续字符......它可以工作(如同一教科书中15页后所示) 。
我们不需要更多的理由来搜索并销毁WITH 块。 它们仅在解释框架中才有意义。
AVOID the WITH Block at all costs (even readability). Two reasons:
To describe this, we have a (broken) example from a Textbook that my co-worker had to ask the author about (it is indeed incorrect, the Names have been changed to protect... whatever):
The OrderBy and ThenBy have No Effect at all. IF you reformat the code by ONLY dropping the With and End With, and adding line continuation characters at the end of the first three lines... it works (as shown 15 pages later in the same textbook).
We don't need any more reason to search and destroy WITH Blocks. They only had meaning in an Interpreted framework.
将其与结构一起使用时存在一个问题,即您无法设置它们的字段,因为您正在处理“with”表达式的本地副本(在进入 with 块时制作),而不是使用 (copy在这种情况下的 an) 对象引用:
https:// learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/with-end-with-statement
猜测如果你传递给 with 语句 a ,编译器可能会更聪明一点结构名称而不是返回结构的表达式,但似乎不是
There's a gotcha when using it with structures, aka you can't set their fields, since you're working on a local copy (made at time of entry in with block) of the "with" expression and not working with a (copy of an) object reference in that case:
https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/with-end-with-statement
guess the compiler could have been a bit more clever if you pass to with statement a structure name instead of an expression that returns a structure, but seems it's not