【问题标题】:How to access the object itself in With ... End With如何在 With ... End With 中访问对象本身
【发布时间】:2010-11-12 06:50:21
【问题描述】:

一些代码来说明我的问题:

With Test.AnObject

    .Something = 1337
    .AnotherThing = "Hello"

    ''// why can't I do this to pass the object itself:
    Test2.Subroutine(.)
    ''// ... and is there an equivalent, other than repeating the object in With?

End With

【问题讨论】:

    标签: vb.net with-statement


    【解决方案1】:

    没有办法引用With语句中引用的对象,只能重复对象本身的名称。

    编辑

    如果你真的想,你可以修改你的对象以返回对它自己的引用

    Public Function Self() as TypeOfAnObject
        Return Me
    End Get
    

    那么你可以使用下面的代码

    With Test.AnObject
        Test2.Subroutine(.Self())
    End With
    

    最后,如果您无法修改对象的代码,您可以(但不一定应该)通过extension method 完成同样的事情。一种通用的解决方案是:

    ' Define in a Module
    <Extension()>
    Public Function Self(Of T)(target As T) As T
        Return target
    End Function
    

    这样称呼:

    Test2.Subroutine(.Self())
    

    With 1
       a = .Self() + 2 ' a now equals 3
    End With
    

    【讨论】:

    • 如果你的类可能被序列化,那么你需要使用函数而不是只读属性!在其他情况下,这里的房产有什么特别的优势吗?
    • 有关属性与方法的讨论,请参阅stackoverflow.com/questions/601621/properties-vs-methods
    • 特别是:“一般来说,方法代表动作,属性代表数据。属性意味着像字段一样使用,这意味着属性不应该计算复杂或产生副作用。当它不违反遵循以下准则,请考虑使用属性而不是方法,因为经验不足的开发人员会发现属性更易于使用。”
    • 另请注意,这个答案有点“hacky”,最好将With目标的引用存储在局部变量中并引用它。
    • 是的,那么您根本不需要With。我确实同意它在概念上更适合作为属性而不是函数。但是作为一个属性,如果你尝试序列化类,它会导致无限递归,所以我最终得到了一个函数。
    【解决方案2】:

    我怀疑你必须重复自己。如果表达式(获取对象)很昂贵,那么可能先将其放入变量中,然后在With 中使用该变量,或者完全丢弃With

    tmp = Test.AnObject;
    tmp.Something = 1337;
    ...
    Test2.Subroutine(tmp);
    

    【讨论】:

      【解决方案3】:

      正如其他人所说,你将不得不写

      Test2.Subroutine(Test.AnObject)
      

      这是一个很好的例子,说明为什么在 VB.Net 中对 With 结构要小心一点。我的观点是,要让它完全值得使用,您确实需要在 With 语句中设置不止一两个属性,和/或在对象上调用不止一两个方法。

      如果有很多,并且您没有在 .SomeProperty =.DoSomething 中穿插其他东西,这对可读性有很大帮助。

      相反,在一大堆其他内容中散布一些点实际上比不使用With 更难阅读。

      在这种情况下,. 字符本身很容易在视觉上丢失,当然,它在语法上是一致的。

      我猜他们只是选择不实施它。 VB 并不是他们真正想要鼓励单字符语言元素的语言,作为 VB.Net 的重度用户,我大致同意这一点。

      底线:如果您使用包含许多包含元素的With 子句,则必须引用对象本身并不是什么大问题。如果您只使用一两个,最好不要一开始就使用With 子句。

      【讨论】:

        【解决方案4】:

        我不确定这本身就是一个“答案”,但它确实说明了另一个需要在 With 中简短引用父级的原因。

        这是一个使用“bare With”的代码示例(我就是这么称呼它的):

        With New frmMySubForm
            .lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = .lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
            ...
        End With
        

        但您实际上无法编写该代码,因为在术语 .Start = .lblLinkLabel.Text.IndexOf("link") 中,编译器希望以 . 开头的任何内容都成为 LinkLabel.Link 的成员,而 .lblLinkLabel 不是。

        我认为最好的办法是能够编写如下内容:

        With New frmMySubForm
            .lblLinkLabel.Links.Add(New LinkLabel.Link With {.Name = "link", .LinkData = "someUrl", .Start = Me.lblLinkLabel.Text.IndexOf("link"), .Length = "link".Length})
            ...
        End With
        

        这里范围内的Me 被视为New frmMySubForm

        是的,我意识到我很挑剔,我可以很容易地分配一个变量等。但是示例表单是我出于偏好而经常使用的东西。

        【讨论】:

          猜你喜欢
          • 2014-08-13
          • 2013-04-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多