15

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
Shog9
  • 156,901
  • 35
  • 231
  • 235

4 Answers4

20

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 an object 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 an object, 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
Jaymin
  • 2,879
  • 3
  • 19
  • 35
Patrick McDonald
  • 64,141
  • 14
  • 108
  • 120
  • If you're class might ever be serialized, then you need to use a function rather than a readonly property! Any particular advantage to a property here in other case? – Adam May 26 '17 at 14:39
  • For discussion of properties vs methods, see https://stackoverflow.com/questions/601621/properties-vs-methods – Patrick McDonald May 27 '17 at 21:24
  • In particular: "In general, methods represent actions and properties represent data. Properties are meant to be used like fields, meaning that properties should not be computationally complex or produce side effects. When it does not violate the following guidelines, consider using a property, rather than a method, because less experienced developers find properties easier to use." – Patrick McDonald May 27 '17 at 21:25
  • Note also that this answer is a bit "hacky" and it would probably b preferable to store a reference to the `With` target in a local variable and refer to that instead. – Patrick McDonald May 27 '17 at 21:27
  • 1
    Yeah, then you don't need the `With` at all. I do agree that it fits conceptually better as a property than a function. But as a property it causes an infinite recursion if you try to serialise the class so I ended up with a function. – Adam May 27 '17 at 21:29
  • You have me convinced! – Patrick McDonald May 29 '17 at 14:49
  • @PatrickMcDonald, thanks sir, you saved my day and some hair :) – Zakir_SZH Oct 18 '19 at 09:50
6

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);
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
5

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.

ChrisA
  • 4,163
  • 5
  • 28
  • 44
0

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.

SteveCinq
  • 1,920
  • 1
  • 17
  • 22