VB.NET中的'With'语句-接受还是避免?
VB.NET中的'With'语句-接受还是避免?
在工作中,我经常在需要在对象构建或早期期间设置某些对象的多个属性的项目中工作。为了方便和易读性,我经常使用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
?我一直认为上述两种情况的编译器生成的代码基本相同,因此我一直选择编写更易读的代码。
admin 更改状态以发布 2023年5月21日
在实际应用中,没有什么非常明显的反对意见。我不是它的粉丝,但这只是个人偏好,没有经验数据表明With
实现会很糟糕。
在.NET中,它编译成与完全限定对象名相同的代码,因此,使用此语法不会有任何性能损失。我确定这一点是通过编译,然后反汇编以下VB.NET 2.0类获得的:
Imports System.Text Public Class Class1 Public Sub Foo() Dim sb As New StringBuilder With sb .Append("foo") .Append("bar") .Append("zap") End With Dim sb2 As New StringBuilder sb2.Append("foo") sb2.Append("bar") sb2.Append("zap") End Sub End Class
反汇编结果如下--注意对sb2
的Append
方法的调用,看起来与sb
的With
语句调用完全一样:
.method public instance void Foo() cil managed { // Code size 91 (0x5b) .maxstack 2 .locals init ([0] class [mscorlib]System.Text.StringBuilder sb, [1] class [mscorlib]System.Text.StringBuilder sb2, [2] class [mscorlib]System.Text.StringBuilder VB$t_ref$L0) IL_0000: nop IL_0001: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor() IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: stloc.2 IL_0009: ldloc.2 IL_000a: ldstr "foo" IL_000f: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string) IL_0014: pop IL_0015: ldloc.2 IL_0016: ldstr "bar" IL_001b: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string) IL_0020: pop IL_0021: ldloc.2 IL_0022: ldstr "zap" IL_0027: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string) IL_002c: pop IL_002d: ldnull IL_002e: stloc.2 IL_002f: newobj instance void [mscorlib]System.Text.StringBuilder::.ctor() IL_0034: stloc.1 IL_0035: ldloc.1 IL_0036: ldstr "foo" IL_003b: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string) IL_0040: pop IL_0041: ldloc.1 IL_0042: ldstr "bar" IL_0047: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string) IL_004c: pop IL_004d: ldloc.1 IL_004e: ldstr "zap" IL_0053: callvirt instance class [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append(string) IL_0058: pop IL_0059: nop IL_005a: ret } // end of method Class1::Foo
因此,如果您喜欢它,认为它更易读,请尽管使用;没有任何明显的理由不这样做。
(顺便说一句,Tom,我很想知道调试器出了什么问题,因为我不记得我曾经在调试器中看到过任何基于With
语句的异常行为,所以我很好奇您看到了什么样的行为。)
如果你有很长的变量名并且最终会出现:
UserHandler.GetUser.First.User.FirstName="Stefan" UserHandler.GetUser.First.User.LastName="Karlsson" UserHandler.GetUser.First.User.Age="39" UserHandler.GetUser.First.User.Sex="Male" UserHandler.GetUser.First.User.Occupation="Programmer" UserHandler.GetUser.First.User.UserID="0" ....and so on
,那么我会使用WITH语句使其更易读:
With UserHandler.GetUser.First.User .FirstName="Stefan" .LastName="Karlsson" .Age="39" .Sex="Male" .Occupation="Programmer" .UserID="0" end with
。在后面的例子中,与第一个例子相比,甚至有性能上的好处,因为在第一个例子中,每次访问用户属性时都会获取用户,而在WITH情况下,我只获取一次用户。我也可以这样获得性能增益:
dim myuser as user =UserHandler.GetUser.First.User myuser.FirstName="Stefan" myuser.LastName="Karlsson" myuser.Age="39" myuser.Sex="Male" myuser.Occupation="Programmer" myuser.UserID="0"
,但我更喜欢使用WITH语句,它看起来更干净。我只是拿这个作为例子,所以不要抱怨有很多关键词的类,另一个例子可能是:WITH RefundDialog.RefundDatagridView.SelectedRows(0)。