VB.NET中的'With'语句-接受还是避免?

16 浏览
0 Comments

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日
0
0 Comments

在实际应用中,没有什么非常明显的反对意见。我不是它的粉丝,但这只是个人偏好,没有经验数据表明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

反汇编结果如下--注意对sb2Append方法的调用,看起来与sbWith语句调用完全一样:

.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语句的异常行为,所以我很好奇您看到了什么样的行为。)

0
0 Comments

如果你有很长的变量名并且最终会出现:

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)。

0