How to access the object itself in With … End With

2019-01-12 03:06发布

问题:

Some code to illustrate my question:

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

回答1:

There is no way to refer to the object referenced in the With statement, other than repeating the name of the object itself.

EDIT

If you really want to, you could modify your AnObject to return a reference to itself

Public Function Self() as TypeOfAnObject
    Return Me
End Get

Then you could use the following code

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

Finally, if you cannot modify the code for AnObject, you could (but not necessarily should) accomplish the same thing via an extension method. One generic solution is:

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

called like so:

Test2.Subroutine(.Self())

or

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


回答2:

I suspect you'll have to repeat yourself. If the expression (to get the object) is expensive, then perhaps drop it into a variable first, and either use that variable in the With, or drop the With completely:

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


回答3:

As others have said, you're going to have to write

Test2.Subroutine(Test.AnObject)

This is a good example of why it's worth being a little careful with the With construct in VB.Net. My view is that to make it worth using at all, you really need to be setting more than one or two properties, and/or calling more than one or two methods on the object in the With statement.

When there are lots, and you're not interspersing the .SomeProperty = , or .DoSomething, with other things, it's a terrific aid to readability.

Conversely, a few dots sprinkled amongst a load of other stuff is actually a lot harder to read than not using With at all.

In this case, . characters on their own could easily get lost visually, although of course, it would be syntactically consistent.

I guess they just chose not to implement it. VB isn't really the sort of language where they want to encourage single character language elements, and as a heavy user of VB.Net, I broadly agree with that.

Bottom line: if you're using a With clause with many contained elements, having to refer to the object itself isn't that big a deal. If you're using it with just one or two, maybe better not to use a With clause in the first place.



回答4:

I'm not sure this is an "answer", per se, but it does illustrate another reason to want a short-hand reference to the parent in a With.

Here's a code sample using a "bare With" (that's what I call it, anyway):

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

But you actually can't code that because in the term .Start = .lblLinkLabel.Text.IndexOf("link") the compiler expects anything starting with . to be a member of LinkLabel.Link, which .lblLinkLabel isn't.

What would be good, I think, is to be able to write something like:

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

where Me in this scope is taken to be New frmMySubForm.

Yes, I realize that I'm being picky and I could easily assign a variable, etc. But the example form is something I use a lot simply out of preference.