121

I have learned quite a bit browsing through Hidden Features of C# and was surprised when I couldn't find something similar for VB.NET.

So what are some of its hidden or lesser known features?

Community
  • 1
  • 1
Sean Gough
  • 1,721
  • 3
  • 26
  • 47

64 Answers64

128

The Exception When clause is largely unknown.

Consider this:

Public Sub Login(host as string, user as String, password as string, _
                            Optional bRetry as Boolean = False)
Try
   ssh.Connect(host, user, password)
Catch ex as TimeoutException When Not bRetry
   ''//Try again, but only once.
   Login(host, user, password, True)
Catch ex as TimeoutException
   ''//Log exception
End Try
End Sub
SteveC
  • 15,808
  • 23
  • 102
  • 173
torial
  • 13,085
  • 9
  • 62
  • 89
  • 9
    useful if you wish to catch a specific SQLException, say -2 which if i remember correctly is network timeout: Catch ex as sqlException where ex.code = -2 – Pondidum Dec 27 '08 at 18:06
  • Wow! I just read this and put it to use immediately to simplify a try/catch block I just wrote last week. I never new this existed. – John M Gant Jun 02 '09 at 16:14
  • 1
    +1 And here's where the NET CLR team blog explains why exception filters are useful http://blogs.msdn.com/clrteam/archive/2009/02/05/catch-rethrow-and-filters-why-you-should-care.aspx – MarkJ Jun 09 '09 at 14:32
  • 5
    Not only is this hidden, but it is also not available in C#. – Cheeso Aug 25 '09 at 20:43
82

Custom Enums

One of the real hidden features of VB is the completionlist XML documentation tag that can be used to create own Enum-like types with extended functionality. This feature doesn't work in C#, though.

One example from a recent code of mine:

'
''' <completionlist cref="RuleTemplates"/>
Public Class Rule
    Private ReadOnly m_Expression As String
    Private ReadOnly m_Options As RegexOptions

    Public Sub New(ByVal expression As String)
        Me.New(expression, RegexOptions.None)
    End Sub

    Public Sub New(ByVal expression As String, ByVal options As RegexOptions)
        m_Expression = expression
        m_options = options
    End Sub

    Public ReadOnly Property Expression() As String
        Get
            Return m_Expression
        End Get
    End Property

    Public ReadOnly Property Options() As RegexOptions
        Get
            Return m_Options
        End Get
    End Property
End Class

Public NotInheritable Class RuleTemplates
    Public Shared ReadOnly Whitespace As New Rule("\s+")
    Public Shared ReadOnly Identifier As New Rule("\w+")
    Public Shared ReadOnly [String] As New Rule("""([^""]|"""")*""")
End Class

Now, when assigning a value to a variable declared as Rule, the IDE offers an IntelliSense list of possible values from RuleTemplates.

/EDIT:

Since this is a feature that relies on the IDE, it's hard to show how this looks when you use it but I'll just use a screenshot:

Completion list in action http://page.mi.fu-berlin.de/krudolph/stuff/completionlist.png

In fact, the IntelliSense is 100% identical to what you get when using an Enum.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • Interesting - could you show an example of how this looks when you consume it? – Brian MacKay Sep 19 '08 at 15:15
  • It looks like someone could still create their own rule by calling the Rule constructor directly? If so, and if you wanted to stop this, could you declare the constructor as "Friend" in your library? – Joel Coehoorn Oct 07 '08 at 14:40
  • Joel, in my example code I intentially didn't forbid this. Rather, I offer the user some common rules and allow the creation of own, specialized rules. You can of course prevent this by marking the constructor as `friend` or by using the same class as the enum: `Rule` instead of `RuleTemplate`. – Konrad Rudolph Oct 08 '08 at 09:06
  • is there somewhere with a list of hidden useful attribute uses? this one at face seems incredible, but I'm not sure yet where I would use it or if it could solve a primary gripe in some cases with having no ability to have a generic restricted to enums. – Maslow May 22 '09 at 13:23
  • @Maslow: there's not attribute involved here. That is an xml comment. – Joel Coehoorn Jun 02 '09 at 15:45
  • @Joel: please enlighten me: how did you prevent highlighting the comment? – Konrad Rudolph Jun 02 '09 at 20:52
  • You can also make a class its own completion list. – Instance Hunter Jul 10 '09 at 14:14
  • Definately a nice bonus when combined with the Strategy pattern (as your example shows) – STW Jul 17 '09 at 19:22
49

Have you noticed the Like comparison operator?

Dim b As Boolean = "file.txt" Like "*.txt"

More from MSDN

Dim testCheck As Boolean

' The following statement returns True (does "F" satisfy "F"?)'
testCheck = "F" Like "F"

' The following statement returns False for Option Compare Binary'
'    and True for Option Compare Text (does "F" satisfy "f"?)'
testCheck = "F" Like "f"

' The following statement returns False (does "F" satisfy "FFF"?)'
testCheck = "F" Like "FFF"

' The following statement returns True (does "aBBBa" have an "a" at the'
'    beginning, an "a" at the end, and any number of characters in '
'    between?)'
testCheck = "aBBBa" Like "a*a"

' The following statement returns True (does "F" occur in the set of'
'    characters from "A" through "Z"?)'
testCheck = "F" Like "[A-Z]"

' The following statement returns False (does "F" NOT occur in the '
'    set of characters from "A" through "Z"?)'
testCheck = "F" Like "[!A-Z]"

' The following statement returns True (does "a2a" begin and end with'
'    an "a" and have any single-digit number in between?)'
testCheck = "a2a" Like "a#a"

' The following statement returns True (does "aM5b" begin with an "a",'
'    followed by any character from the set "L" through "P", followed'
'    by any single-digit number, and end with any character NOT in'
'    the character set "c" through "e"?)'
testCheck = "aM5b" Like "a[L-P]#[!c-e]"

' The following statement returns True (does "BAT123khg" begin with a'
'    "B", followed by any single character, followed by a "T", and end'
'    with zero or more characters of any type?)'
testCheck = "BAT123khg" Like "B?T*"

' The following statement returns False (does "CAT123khg" begin with'
'    a "B", followed by any single character, followed by a "T", and'
'    end with zero or more characters of any type?)'
testCheck = "CAT123khg" Like "B?T*"
Alex Essilfie
  • 12,339
  • 9
  • 70
  • 108
Parsa
  • 997
  • 1
  • 15
  • 38
  • 3
    wait, what? That's new to me! Hmm, that's a helluva lot better than the alternative with VB.NET string manipulation :D – STW May 05 '09 at 14:37
  • ..!! I didn't know that although I worked on several vb.net projects! Interesting feature... – Meta-Knight May 13 '09 at 03:44
  • woooooooooooooooooooooooow! thanks! that's awsome! does it work in ELinq, DLinq too? what about XLinq? – Shimmy Weitzhandler Jul 14 '09 at 09:49
  • @dotjoe Hmm? There's nothing 'lazy' about these globs. – Josh Lee Nov 27 '09 at 07:16
  • How does this perform, whats happening under the hood? Is it s synonym for reg ex libraries? – brumScouse Aug 25 '10 at 22:00
  • Nope, compiles to a simple call to a static function: Microsoft.VisualBasic.CompilerServices.LikeOperator.LikeString. It may look like a cheat to some people, but it gets very interesting when it comes to LINQ. – Parsa Aug 26 '10 at 08:23
  • This 'hidden feature' was was in VB6. The book I learnt VB6 included it so I've always known of its existence. – Alex Essilfie Jan 10 '11 at 14:38
  • "Like" is my favorite handy VB string tool ever. As a perl and regex fanatic, I much appreciate the capability. – Br.Bill Mar 11 '11 at 23:29
48

Typedefs

VB knows a primitive kind of typedef via Import aliases:

Imports S = System.String

Dim x As S = "Hello"

This is more useful when used in conjunction with generic types:

Imports StringPair = System.Collections.Generic.KeyValuePair(Of String, String)
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
45

Oh! and don't forget XML Literals.

Dim contact2 = _
        <contact>
          <name>Patrick Hines</name>
          <%= From p In phoneNumbers2 _
            Select <phone type=<%= p.Type %>><%= p.Number %></phone> _
          %>
        </contact>
Nescio
  • 27,645
  • 10
  • 53
  • 72
  • That's what I was going to say. In fact, I've used XML literals for a purpose in which it wasn't intended. I used it to produce Javascript... http://swortham.blogspot.com/2009/03/vb-2008.html – Steve Wortham Jul 13 '09 at 21:26
  • 9
    Among other things, you can use XML Literals to get around ugly string escaping, e.g. when you're using strings that themselves contain double quotes. Just put the string inside an XML Literal and call Value, like this: `This string contains "quotes" and it's OK..Value` (I found this especially handy when writing tests on parsing CSV files where every field was in quotes. It would *not* have been fun to escape all those quotes by hand in my test lines.) – Ryan Lundy Dec 17 '09 at 22:26
  • 2
    @Kyralessa: +1, great comment. In fact, it's also a great way to specify multi-line strings (hugs SQL statements, etc.). – Heinzi Dec 27 '09 at 19:41
  • Inline XML is one of the worst VB.NET features ever to be conceived. Unsubstantiated fact. – Grant Thomas Feb 01 '12 at 15:01
39

Object initialization is in there too!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
Nescio
  • 27,645
  • 10
  • 53
  • 72
  • 1
    I can't believe they went with curly braces. We already have a With statement.. they could have just reused that syntax. – Sam Axe May 19 '09 at 19:26
  • 2
    I know, it's made just to show you that there is no cop on the road... lol JK – Shimmy Weitzhandler Jul 13 '09 at 15:56
  • 4
    Thi sis what happens when all of the compiler writers are themselves C/C++ programmers at heart. They keep slipping C syntax into other languages because they cannot conceive of anything being better. – RBarryYoung Sep 19 '09 at 06:28
38

DirectCast

DirectCast is a marvel. On the surface, it works similar to the CType operator in that it converts an object from one type into another. However, it works by a much stricter set of rules. CType's actual behaviour is therefore often opaque and it's not at all evident which kind of conversion is executed.

DirectCast only supports two distinct operations:

  • Unboxing of a value type, and
  • upcasting in the class hierarchy.

Any other cast will not work (e.g. trying to unbox an Integer to a Double) and will result in a compile time/runtime error (depending on the situation and what can be detected by static type checking). I therefore use DirectCast whenever possible, as this captures my intent best: depending on the situation, I either want to unbox a value of known type or perform an upcast. End of story.

Using CType, on the other hand, leaves the reader of the code wondering what the programmer really intended because it resolves to all kinds of different operations, including calling user-defined code.

Why is this a hidden feature? The VB team has published a guideline1 that discourages the use of DirectCast (even though it's actually faster!) in order to make the code more uniform. I argue that this is a bad guideline that should be reversed: Whenever possible, favour DirectCast over the more general CType operator. It makes the code much clearer. CType, on the other hand, should only be called if this is indeed intended, i.e. when a narrowing CType operator (cf. operator overloading) should be called.


1) I'm unable to come up with a link to the guideline but I've found Paul Vick's take on it (chief developer of the VB team):

In the real world, you're hardly ever going to notice the difference, so you might as well go with the more flexible conversion operators like CType, CInt, etc.


(EDIT by Zack: Learn more here: How should I cast in VB.NET?)

Community
  • 1
  • 1
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • I actually like TryCast() a bit better. It won't throw an exception, just return Nothing if the cast fails. If you expect the cast to fail often, it's faster than If TypeOf x Is T...DirectCast(x,T) and certainly faster than catching the exception if DirectCast fails. – Bob King Sep 22 '08 at 22:48
  • 6
    DirectCast() and TryCast() are invaluable when used correctly as a pair. DirectCast() should be used if the object being cast is *always* expected to be the target type (if it isn't you'll get an error, a good thing since it's an unexpected situation). TryCast() should be used if the object being cast *could* be of the target type, or of several target types. Using One or the other exclusively will either lead to extra overhead (if typeof x is y then directcast(x, y) is inefficient) or to avoiding valid errors (using TryCast() for cases where the object should *always* be the target type) – STW May 05 '09 at 14:28
  • Yoooder: 100% correct. It's a shame I didn't mention `TryCast` back then since I mainly had a bone to pick with the pervasive use of `CType`. – Konrad Rudolph May 05 '09 at 17:35
  • @Maslow: of course it doesn't, since Enums are value types and `TryCast` only works on reference types, as per the documentation. – Konrad Rudolph May 22 '09 at 15:03
  • +1: Heh. I've got to admit, I just read this and thought "Oh yeah, DirectCast, how did I forget about that?" And then I used it on my very next line of code (as I really dislike CType). – RBarryYoung Sep 19 '09 at 06:53
37

If conditional and coalesce operator

I don't know how hidden you'd call it, but the Iif([expression],[value if true],[value if false]) As Object function could count.

It's not so much hidden as deprecated! VB 9 has the If operator which is much better and works exactly as C#'s conditional and coalesce operator (depending on what you want):

Dim x = If(a = b, c, d)

Dim hello As String = Nothing
Dim y = If(hello, "World")

Edited to show another example:

This will work with If(), but cause an exception with IIf()

Dim x = If(b<>0,a/b,0)
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • Nice, I didn't know this! I just used IIF yesterday so I'm going to revisit that code block. – Sean Gough Sep 19 '08 at 14:16
  • Nice to know. It's not exactly deprecated, though, if your job has you targeting the 2.0 framework. – Sam Erwin Sep 19 '08 at 16:17
  • It *is* deprecated and it doesn't matter which platform you target, the new `If` operator works on both since it's a language feature that doesn't rely on the framework. – Konrad Rudolph Sep 19 '08 at 17:26
  • 4
    Tell VS 2005 that. Not all of us get to work with the latest and greatest. – Sam Erwin Sep 19 '08 at 18:31
  • Only and huuuge problem with this it's not type-safety, it returns and object which is rubbish 99% of the time. – dr. evil Nov 27 '08 at 16:16
  • 3
    @Slough, nonsense. This method is 100% type safe and it returns an object of the same type as its (second and third) argument. Additionally, there must be a widening conversion between the arguments, else there will be a compile error because the types don't match. – Konrad Rudolph Nov 27 '08 at 17:53
  • 1
    Yes, its IIf() that is not type safe – Pondidum Jul 08 '09 at 12:53
  • Sort of a simplified trinary operator, providing some equivalence to C & perl's ? operator. – Br.Bill Mar 11 '11 at 23:33
  • 2
    @Br.Bill In fact, it’s *completely equivalent* to C and Perl’s `:?` operator, it’s not just a simplified version. – Konrad Rudolph Mar 12 '11 at 08:55
32

This is a nice one. The Select Case statement within VB.Net is very powerful.

Sure there is the standard

Select Case Role
  Case "Admin"
         ''//Do X
  Case "Tester"
         ''//Do Y
  Case "Developer"
         ''//Do Z
  Case Else
       ''//Exception case
End Select

But there is more...

You can do ranges:

Select Case Amount
 Case Is < 0
    ''//What!!
 Case 0 To 15
   Shipping = 2.0
 Case 16 To 59
    Shipping = 5.87
 Case Is > 59
    Shipping = 12.50
 Case Else
    Shipping = 9.99
 End Select

And even more...

You can (although may not be a good idea) do boolean checks on multiple variables:

Select Case True
 Case a = b
    ''//Do X
 Case a = c
    ''//Do Y
 Case b = c
    ''//Do Z
 Case Else
   ''//Exception case
 End Select
John
  • 29,788
  • 18
  • 89
  • 130
torial
  • 13,085
  • 9
  • 62
  • 89
  • 5
    Actually you missed a couple: a) use of "Select Case True" to test more than one variable, b) use of "Case A, B, ..." form, and even c) applying the ":" to in-line the execution statement with the condition clause (though many do not like this). – RBarryYoung Sep 19 '09 at 06:24
  • 6
    Please don't use Select Case True. Just use an If statement. – Ryan Lundy Dec 02 '09 at 21:29
  • 4
    I find Select Case True much easier to read than a giant ifelse statement. – dwidel Dec 30 '10 at 16:43
  • The trouble with `Select Case True` is that it *looks* as if it evaluates *each* of the `Case` statements and runs the code for each one which is true. But in fact it evaluates them one-by-one and only runs the code for the *first* one which is true. The syntax for `If` is much clearer in this regard (`If...Else If...Else If...Else`). – Ryan Lundy Dec 30 '11 at 18:56
31

One major time saver I use all the time is the With keyword:

With ReallyLongClassName
    .Property1 = Value1
    .Property2 = Value2
    ...
End With

I just don't like typing more than I have to!

Jasha87
  • 327
  • 2
  • 3
  • But it also create some hidden bugs, especially when you have With within With – Varun Mahajan Sep 19 '08 at 14:24
  • 2
    I didn't even know you could put a new With within an existing With. That's just sloppy! – Bob King Sep 22 '08 at 22:44
  • 2Bob: it's not sloppy, I'd suggest.. it's just a language construct to be used with care. For setting lots of properties in successive lines, it's great, but finding a random .Foo in a complex piece of code and then having to hunt the With statement x lines above is not a good use of the feature. – ChrisA Dec 19 '08 at 15:50
  • 2
    Wish C# has this? Or have I been asleep and is that in the C# hidden-features answers already...? ;-) – peSHIr Jan 15 '09 at 14:41
  • Also... during debugging you can't step over and see the value of the property... you must took the ReallyLongClassName into the Watch list. – Romias Mar 14 '09 at 17:04
  • @Romias: wrong. The debugger can indeed show the value of a with block member in a hover-over. – Sam Axe May 19 '09 at 19:17
  • 1
    @Boo: You're right but it's still an annoyance that you can't add it to the Watch list. – Meta-Knight Jun 22 '09 at 17:50
  • Gotta agree, unless you just prefer the style of dense text in your code (ugh) – DarinH Mar 22 '11 at 20:20
  • I just thought I'd mention: With can be dangerous in a multithreaded environment since the compiler creates a local variable that is only in-scope within the With block. If something is posted to another thread and not processed until after the With block is exited, you can unexpectedly get a null reference. Maybe this is obvious to everyone else, but that fact burned me before. See the answer to [this question](http://stackoverflow.com/questions/3886187/vb-net-trying-to-modify-a-generic-invoke-method-to-a-generic-begininvoke-method) for an example. – Brian Mulcahy Apr 04 '11 at 23:11
31

The best and easy CSV parser:

Microsoft.VisualBasic.FileIO.TextFieldParser

By adding a reference to Microsoft.VisualBasic, this can be used in any other .Net language, e.g. C#

cjk
  • 45,739
  • 9
  • 81
  • 112
26
  • AndAlso/OrElse logical operators

(EDIT: Learn more here: Should I always use the AndAlso and OrElse operators?)

Community
  • 1
  • 1
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • I wouldn't call it hidden at all, If Contact IsNot Nothing AndAlso Contact.ContactId > 0 Then Do it, If you will use And you will have an exception thrown. – Shimmy Weitzhandler Jul 14 '09 at 09:55
25

In vb there is a different between these operators:

/ is Double
\ is Integer ignoring the remainder

Sub Main()
    Dim x = 9 / 5  
    Dim y = 9 \ 5  
    Console.WriteLine("item x of '{0}' equals to {1}", x.GetType.FullName, x)
    Console.WriteLine("item y of '{0}' equals to {1}", y.GetType.FullName, y)

    'Results:
    'item x of 'System.Double' equals to 1.8
    'item y of 'System.Int32' equals to 1
End Sub
Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
  • 1
    i learned this the hard way when trying to find a needle in a million lines of code. regular versus integer division. good tip! – Jason Irwin Sep 18 '09 at 18:47
25

Static members in methods.

For example:

Function CleanString(byval input As String) As String
    Static pattern As New RegEx("...")

    return pattern.Replace(input, "")
End Function

In the above function, the pattern regular expression will only ever be created once no matter how many times the function is called.

Another use is to keep an instance of "random" around:

Function GetNextRandom() As Integer
    Static r As New Random(getSeed())

    Return r.Next()
End Function 

Also, this isn't the same as simply declaring it as a Shared member of the class; items declared this way are guaranteed to be thread-safe as well. It doesn't matter in this scenario since the expression will never change, but there are others where it might.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • 1
    One use of this is to keep a counter that will increment each time the method is called. If the variable is marked Static, it won't be reinitialized on each method call; it'll only be initialized on the first call, and thereafter will retain its value. – Ryan Lundy Jan 06 '09 at 20:56
  • This is the reason why static class members are named "shared" in VB.NET – Enrico Campidoglio Apr 09 '09 at 20:15
  • Static is bad form in VB.NET even more than it was in classic VB. Static variables should be avoided whenever and wherever possible. – Sam Axe May 19 '09 at 19:39
  • 6
    @Boo - that's pretty sweeping. What's your justification? I think static variables are useful. – MarkJ Jun 09 '09 at 14:36
  • 4
    Static, used as in the examples above, allows a unique form of encapsulation: class-level variables that have method-level scope. Without it, you'd have to create a class-level variable that would be accessible to any class member, even if you're only using it in one method. – Ryan Lundy Dec 02 '09 at 21:41
  • @Enrico, well that's part of it. But also static isn't really an OOP term. It's more of a assmebly/C term meaning "this field is in a fixed place in memory". – Jonathan Allen Jul 11 '10 at 01:06
  • beware: I believe it is only 'static' for multiple calls to the method in that particular object, NOT across all instances of the object. Tell me if I'm wrong, start your message with @fastal – FastAl Sep 07 '10 at 19:04
23

Custom Events

Though seldom useful, event handling can be heavily customized:

Public Class ApplePie
    Private ReadOnly m_BakedEvent As New List(Of EventHandler)()

    Custom Event Baked As EventHandler
        AddHandler(ByVal value As EventHandler)
            Console.WriteLine("Adding a new subscriber: {0}", value.Method)
            m_BakedEvent.Add(value)
        End AddHandler

        RemoveHandler(ByVal value As EventHandler)
            Console.WriteLine("Removing subscriber: {0}", value.Method)
            m_BakedEvent.Remove(value)
        End RemoveHandler

        RaiseEvent(ByVal sender As Object, ByVal e As EventArgs)
            Console.WriteLine("{0} is raising an event.", sender)
            For Each ev In m_BakedEvent
                ev.Invoke(sender, e)
            Next
        End RaiseEvent
    End Event

    Public Sub Bake()
        ''// 1. Add ingredients
        ''// 2. Stir
        ''// 3. Put into oven (heated, not pre-heated!)
        ''// 4. Bake
        RaiseEvent Baked(Me, EventArgs.Empty)
        ''// 5. Digest
    End Sub
End Class

This can then be tested in the following fashion:

Module Module1
    Public Sub Foo(ByVal sender As Object, ByVal e As EventArgs)
        Console.WriteLine("Hmm, freshly baked apple pie.")
    End Sub

    Sub Main()
        Dim pie As New ApplePie()
        AddHandler pie.Baked, AddressOf Foo
        pie.Bake()
        RemoveHandler pie.Baked, AddressOf Foo
    End Sub
End Module
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • seems cool, but if I ever need this I think I will have done something wrong ;-). It just seems against the KISS principle. – chrissie1 Sep 19 '08 at 18:38
  • 4
    It is really, really useful when you want to make sure every sink gets the event even if one or more throw an exception. – Jonathan Allen Oct 04 '08 at 05:40
  • Another value (I just read it on the MSDN site) is if your class throws lots of events, you can force it to use a hash table/dictionary as a container, rather than declaring a field for each event. http://msdn.microsoft.com/en-us/library/8627sbea(VS.71).aspx – torial Dec 13 '08 at 00:46
  • Cool. I thought this one of the features that set apart C# and VB.NET (as in one can, but the other has no syntax for it). Nice to at least know I was wrong in this respect. – peSHIr Jan 15 '09 at 14:40
23

I really like the "My" Namespace which was introduced in Visual Basic 2005. My is a shortcut to several groups of information and functionality. It provides quick and intuitive access to the following types of information:

  • My.Computer: Access to information related to the computer such as file system, network, devices, system information, etc. It provides access to a number of very important resources including My.Computer.Network, My.Computer.FileSystem, and My.Computer.Printers.
  • My.Application: Access to information related to the particular application such as name, version, current directory, etc.
  • My.User: Access to information related to the current authenticated user.
  • My.Resources: Access to resources used by the application residing in resource files in a strongly typed manner.
  • My.Settings: Access to configuration settings of the application in a strongly typed manner.
splattne
  • 102,760
  • 52
  • 202
  • 249
21

I just found an article talking about the "!" operator, also know as the "dictionary lookup operator". Here's an excerpt from the article at: http://panopticoncentral.net/articles/902.aspx

The technical name for the ! operator is the "dictionary lookup operator." A dictionary is any collection type that is indexed by a key rather than a number, just like the way that the entries in an English dictionary are indexed by the word you want the definition of. The most common example of a dictionary type is the System.Collections.Hashtable, which allows you to add (key, value) pairs into the hashtable and then retrieve values using the keys. For example, the following code adds three entries to a hashtable, and looks one of them up using the key "Pork".

Dim Table As Hashtable = New Hashtable
Table("Orange") = "A fruit"
Table("Broccoli") = "A vegetable"
Table("Pork") = "A meat" 
Console.WriteLine(Table("Pork"))

The ! operator can be used to look up values from any dictionary type that indexes its values using strings. The identifier after the ! is used as the key in the lookup operation. So the above code could instead have been written:

Dim Table As Hashtable = New Hashtable
Table!Orange = "A fruit"
Table!Broccoli = "A vegetable"
Table!Pork = "A meat"
Console.WriteLine(Table!Pork)

The second example is completely equivalent to the first, but just looks a lot nicer, at least to my eyes. I find that there are a lot of places where ! can be used, especially when it comes to XML and the web, where there are just tons of collections that are indexed by string. One unfortunate limitation is that the thing following the ! still has to be a valid identifier, so if the string you want to use as a key has some invalid identifier character in it, you can't use the ! operator. (You can't, for example, say "Table!AB$CD = 5" because $ isn't legal in identifiers.) In VB6 and before, you could use brackets to escape invalid identifiers (i.e. "Table![AB$CD]"), but when we started using brackets to escape keywords, we lost the ability to do that. In most cases, however, this isn't too much of a limitation.

To get really technical, x!y works if x has a default property that takes a String or Object as a parameter. In that case, x!y is changed into x.DefaultProperty("y"). An interesting side note is that there is a special rule in the lexical grammar of the language to make this all work. The ! character is also used as a type character in the language, and type characters are eaten before operators. So without a special rule, x!y would be scanned as "x! y" instead of "x ! y". Fortunately, since there is no place in the language where two identifiers in a row are valid, we just introduced the rule that if the next character after the ! is the start of an identifier, we consider the ! to be an operator and not a type character.

torial
  • 13,085
  • 9
  • 62
  • 89
19

This is built-in, and a definite advantage over C#. The ability to implement an interface Method without having to use the same name.

Such as:

Public Sub GetISCSIAdmInfo(ByRef xDoc As System.Xml.XmlDocument) Implements IUnix.GetISCSIInfo

End Sub
torial
  • 13,085
  • 9
  • 62
  • 89
17

Forcing ByVal

In VB, if you wrap your arguments in an extra set of parentheses you can override the ByRef declaration of the method and turn it into a ByVal. For instance, the following code produces 4, 5, 5 instead of 4,5,6

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim R = 4
    Trace.WriteLine(R)
    Test(R)
    Trace.WriteLine(R)
    Test((R))
    Trace.WriteLine(R)
End Sub
Private Sub Test(ByRef i As Integer)
    i += 1
End Sub

See Argument Not Being Modified by Procedure Call - Underlying Variable

Chris Haas
  • 53,986
  • 12
  • 141
  • 274
  • 6
    Oh my goodness... that's a remarkable feature, though I don't think I'd know what it was doing if I read it in someone else's code. If you have to comment it just to know what it's doing, you might as well have made the throw away variable to pass in instead. – mattmc3 Jul 22 '10 at 00:10
  • 7
    This is actually a side effect of the use of parenthesis - Parenthesis create a temp value of what's inside, even if just one item. This effect KILLED ME in vb6 - Sub calls didn't take parens, but me coming from C instinctively put the parens in. 6.0 blew up on multiple parameters, but for one parameter subs, it happily passed a temp value and REFUSED to honor my 'byref'. Happened about every 3 years, about the time it took me to forget the last incident. – FastAl Sep 07 '10 at 19:11
16

Passing parameters by name and, so reordering them

Sub MyFunc(Optional msg as String= "", Optional displayOrder As integer = 0)

    'Do stuff

End function

Usage:

Module Module1

    Sub Main()

        MyFunc() 'No params specified

    End Sub

End Module

Can also be called using the ":=" parameter specification in any order:

MyFunc(displayOrder:=10, msg:="mystring")
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Rich
  • 111
  • 2
  • 7
  • Wow, this is super cool! I seen this when using Web Services, etc but I didn't know you could do this any any ol' normal method. – RichC Dec 22 '08 at 16:26
  • 2
    Definately a *very* handy tool when you encounter a method that takes too many arguments. I try to name each parameter and put the name:=value on its own line. It's a lot more intuitive and clean for methods that take > 5 (my rule of thumb) parameters. – STW May 05 '09 at 14:33
  • Especially useful for Office automation, where you have to cope with methods with dozens of optional arguments. – MarkJ Jun 09 '09 at 14:38
  • 1
    What's also cool is that you can *mix* the two: start by specifying the required parameters in order, then switch to named parameters for the optional arguments! – RBarryYoung Sep 19 '09 at 07:10
15

The Using statement is new as of VB 8, C# had it from the start. It calls dispose automagically for you.

E.g.

Using lockThis as New MyLocker(objToLock)

End Using
torial
  • 13,085
  • 9
  • 62
  • 89
  • 23
    It's worth noting (only because I've forgotten at least twice) that you can have one Using statement wrap several Disposable objects. The syntax is "Using objA as new object, objB as new object...." It's a lot cleaner than nesting multiple Using statements. – STW May 05 '09 at 14:35
  • Definately one of my favorites as well. – Sam Axe May 19 '09 at 19:31
14

Import aliases are also largely unknown:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form
torial
  • 13,085
  • 9
  • 62
  • 89
  • 1
    I think we had the same idea. – chrissie1 Sep 19 '08 at 14:27
  • 3
    @Boo -- here's a simple example where import aliases are not evil. http://stackoverflow.com/questions/92869/nunit-vs-visual-studio-2008s-test-projects-for-unit-testing/547199#547199 – torial Jun 04 '09 at 00:04
  • Okay - there's an obvious avenue for abuse, but regardless of @torial's rant this is a great feature. Everytime I include System.Text.RegularExpressions I risk having name collisions with the "Group" class since that's a common class name. The alias lets you avoid having to fully qualify ambiguous classes which is a huge time saver and actually **enhances** readability when used properly. The feature is great, but your specific example does sort of invite some ridicule - sorry to say. – mattmc3 Jul 22 '10 at 00:01
14

If you need a variable name to match that of a keyword, enclose it with brackets. Not nec. the best practice though - but it can be used wisely.

e.g.

Class CodeException
Public [Error] as String
''...
End Class

''later
Dim e as new CodeException
e.Error = "Invalid Syntax"

e.g. Example from comments(@Pondidum):

Class Timer
Public Sub Start()
''...
End Sub

Public Sub [Stop]()
''...
End Sub
torial
  • 13,085
  • 9
  • 62
  • 89
  • I think this example would be better if you didn't use "If" as the example keyword. – Sean Gough Sep 19 '08 at 18:53
  • 4
    timer.Start and timer.Stop spring to mind as examples of good use of this – Pondidum Dec 26 '08 at 20:13
  • 5
    +1 for pointing it out with a disclaimer. There are several framework classes that require this to resolve correctly, such as [Assembly] – STW May 05 '09 at 14:36
  • 5
    [Enum] is another good example of a case where you need the brackets in order to use the class instead of the keyword. – Ryan Lundy Dec 17 '09 at 22:30
14

Consider the following event declaration

Public Event SomethingHappened As EventHandler

In C#, you can check for event subscribers by using the following syntax:

if(SomethingHappened != null)
{
  ...
}

However, the VB.NET compiler does not support this. It actually creates a hidden private member field which is not visible in IntelliSense:

If Not SomethingHappenedEvent Is Nothing OrElse SomethingHappenedEvent.GetInvocationList.Length = 0 Then
...
End If

More Information:

http://jelle.druyts.net/2003/05/09/BehindTheScenesOfEventsInVBNET.aspx http://blogs.msdn.com/vbteam/archive/2009/09/25/testing-events-for-nothing-null-doug-rothaus.aspx

Technobabble
  • 996
  • 9
  • 25
  • Why would you ever want to do that? I can't imagine a use case where you need to know the number of subscribers to an event in VB. – Konrad Rudolph Sep 19 '08 at 16:58
  • In certain circumstances, C# throws an exception if you raise the event and there are no handlers. VB.Net will not. Hence the need to check. – Joel Coehoorn Sep 19 '08 at 20:23
  • 2
    I used this for a business object event which raised validation error messages to the subscribers. I wanted to check to see if the event was being handled so that I knew the validation errors were being received. Otherwise, I had the business object throw an exception. – Technobabble Nov 18 '08 at 17:12
  • 2
    Another handy use for this private member is to get the Event's invocation list. I've used it in several cases to fire the event in an async manner to all callers (prevents Listener A from modifying the event before Listener B receives it; also it prevents Listener A from delaying the delivery to Listener B). I've used this a lot in custom data sync scenarios, and also in APIs. – STW May 05 '09 at 14:31
13

There are a couple of answers about XML Literals, but not about this specific case:

You can use XML Literals to enclose string literals that would otherwise need to be escaped. String literals that contain double-quotes, for instance.

Instead of this:

Dim myString = _
    "This string contains ""quotes"" and they're ugly."

You can do this:

Dim myString = _
    <string>This string contains "quotes" and they're nice.</string>.Value

This is especially useful if you're testing a literal for CSV parsing:

Dim csvTestYuck = _
    """Smith"", ""Bob"", ""123 Anywhere St"", ""Los Angeles"", ""CA"""

Dim csvTestMuchBetter = _
    <string>"Smith", "Bob", "123 Anywhere St", "Los Angeles", "CA"</string>.Value

(You don't have to use the <string> tag, of course; you can use any tag you like.)

Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
12

DateTime can be initialized by surrounding your date with #

Dim independanceDay As DateTime = #7/4/1776#

You can also use type inference along with this syntax

Dim independanceDay = #7/4/1776#

That's a lot nicer than using the constructor

Dim independanceDay as DateTime = New DateTime(1776, 7, 4)
danlash
  • 678
  • 1
  • 6
  • 13
12

You can have 2 lines of code in just one line. hence:

Dim x As New Something : x.CallAMethod
Josh Lee
  • 171,072
  • 38
  • 269
  • 275
Parsa
  • 997
  • 1
  • 15
  • 38
11

Optional Parameters

Optionals are so much easier than creating a new overloads, such as :

Function CloseTheSystem(Optional ByVal msg AS String = "Shutting down the system...")
   Console.Writeline(msg)
   ''//do stuff
End Function
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
dr. evil
  • 26,944
  • 33
  • 131
  • 201
  • 1
    I wasn't aware that C# was going to get them. They are nice, but you have to be careful to use them *only* where you're sure the code won't be consumed by C# since it doesn't support them. FxCop/Code Analysis will tell you to overload the method instead. – STW May 05 '09 at 14:34
  • ...I just found a great use for Optional parameters, while still keeping them out of production code. I wrote-up a short post about it on my site: http://yoooder.com/wordpress/?p=62 – STW Aug 21 '09 at 20:30
  • 2
    Ah, I despise this so much... But useful for Office automation – dance2die Oct 20 '09 at 02:39
9

Title Case in VB.Net can be achieved by an old VB6 fxn:

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
torial
  • 13,085
  • 9
  • 62
  • 89
  • 1
    its also in the textinfo class. not sure what namespace that is in. probably system.text – Shawn Oct 13 '08 at 04:23
  • You are better of to be .net language neutral and use the Globalization TextInfo class to convert ToTitleCase. If you code ever needs to be converted to C# you'll have lots of little nasties that require Microsoft.VisualBasic – Jeremy Jun 29 '11 at 04:03
9

Properties with parameters

I have been doing some C# programming, and discovered a feature that was missing that VB.Net had, but was not mentioned here.

An example of how to do this (as well as the c# limitation) can be seen at: Using the typical get set properties in C#... with parameters

I have excerpted the code from that answer:

Private Shared m_Dictionary As IDictionary(Of String, Object) = _
             New Dictionary(Of String, Object)

Public Shared Property DictionaryElement(ByVal Key As String) As Object
    Get
        If m_Dictionary.ContainsKey(Key) Then
            Return m_Dictionary(Key)
        Else
            Return [String].Empty
        End If
    End Get
    Set(ByVal value As Object)
        If m_Dictionary.ContainsKey(Key) Then
            m_Dictionary(Key) = value
        Else
            m_Dictionary.Add(Key, value)
        End If

    End Set
End Property
Community
  • 1
  • 1
torial
  • 13,085
  • 9
  • 62
  • 89
  • This is interesting, but I'm not entirely sure where this would be useful. myObj.Something("abc") looks more like you're accessing a Function than a property. Not sure what this buys you. – mattmc3 Jul 22 '10 at 00:06
  • I hate ambiguity. What should it be. A method, or a property. Some refactoring tools suggest creating both in certain situations too, looks like they dont even know... – brumScouse Aug 25 '10 at 21:57
9

Stack/group multiple using statements together:

Dim sql As String = "StoredProcedureName"
Using cn As SqlConnection = getOpenConnection(), _
      cmd As New SqlCommand(sql, cn), _
      rdr As SqlDataReader = cmd.ExecuteReader()

    While rdr.Read()

        ''// Do Something

    End While

End Using

To be fair, you can do it in C#, too. But a lot of people don't know about this in either language.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • @ck - how is this done with C#? Can you please provide a link, sorry from all the VBers, I am also one, but education is before manners... – Shimmy Weitzhandler Jul 13 '09 at 19:58
  • 1
    @Shimmy: if they are of the same type you can just comma delimit them. If they are different types, each gets it's own using statement, but the additional objects go on a new line (without the need for a new scope block). I have an example handy at this question: http://stackoverflow.com/questions/436026 – Joel Coehoorn Jul 13 '09 at 20:11
  • I cannot see how this could be practical in any code, especially for readability. – Jeremy Jun 29 '11 at 04:07
  • @Jeremy - I provided a very practical, readable, and common example. – Joel Coehoorn Jun 29 '11 at 04:09
  • @Joel I meant 'practical' in the sense that in a workplace where everyone has their own coding style writing using statements like this could cause some issues. I can imagine other co-workers seeing this and cleaning it up as they think its 'abnormal' or something. Don't get me wrong its a cool concept. – Jeremy Jun 29 '11 at 04:18
8

One of the features I found really useful and helped to solve many bugs is explicitly passing arguments to functions, especially when using optional.

Here is an example:

Public Function DoSomething(byval x as integer, optional y as boolean=True, optional z as boolean=False)
' ......
End Function

then you can call it like this:

DoSomething(x:=1, y:=false)
DoSomething(x:=2, z:=true)
or
DoSomething(x:=3,y:=false,z:=true)

This is much cleaner and bug free then calling the function like this

DoSomething(1,true)
Youssef
  • 728
  • 2
  • 10
  • 22
7
  • Child namespaces are in scope after importing their parent. For exampe, rather than having to import System.IO or say System.IO.File to use the File class, you can just say IO.File. That's a simple example: there are places where the feature really comes in handy, and C# doesn't do it.
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • I just hate this *feature* since I get lost without looking at namespace in the beginning of the file... but still +1! – dance2die Oct 20 '09 at 02:42
7

If you never knew about the following you really won't believe it's true, this is really something that C# lacks big time:

(It's called XML literals)

Imports <xmlns:xs="System">

Module Module1

  Sub Main()
    Dim xml =
      <root>
        <customer id="345">
          <name>John</name>
          <age>17</age>
        </customer>
        <customer id="365">
          <name>Doe</name>
          <age>99</age>
        </customer>
      </root>

    Dim id = 1
    Dim name = "Beth"
    DoIt(
      <param>
        <customer>
          <id><%= id %></id>
          <name><%= name %></name>
        </customer>
      </param>
    )

    Dim names = xml...<name>
    For Each n In names
      Console.WriteLine(n.Value)
    Next

    For Each customer In xml.<customer>
      Console.WriteLine("{0}: {1}", customer.@id, customer.<age>.Value)
    Next

    Console.Read()
  End Sub

  Private Sub CreateClass()
    Dim CustomerSchema =
      XDocument.Load(CurDir() & "\customer.xsd")

    Dim fields =
      From field In CustomerSchema...<xs:element>
      Where field.@type IsNot Nothing
      Select
        Name = field.@name,
        Type = field.@type

    Dim customer = 
      <customer> Public Class Customer 
<%= From field In fields Select <f> 
Private m_<%= field.Name %> As <%= GetVBPropType(field.Type) %></f>.Value %>

                     <%= From field In fields Select <p> 
Public Property <%= field.Name %> As <%= GetVBPropType(field.Type) %>
 Get 
Return m_<%= field.Name %> 
End Get
 Set(ByVal value As <%= GetVBPropType(field.Type) %>)
 m_<%= field.Name %> = value 
End Set
 End Property</p>.Value %> 
End Class</customer>

    My.Computer.FileSystem.WriteAllText("Customer.vb",
                                        customer.Value,
                                        False,
                                        System.Text.Encoding.ASCII)

  End Sub

  Private Function GetVBPropType(ByVal xmlType As String) As String
    Select Case xmlType
      Case "xs:string"
        Return "String"
      Case "xs:int"
        Return "Integer"
      Case "xs:decimal"
        Return "Decimal"
      Case "xs:boolean"
        Return "Boolean"
      Case "xs:dateTime", "xs:date"
        Return "Date"
      Case Else
        Return "'TODO: Define Type"
    End Select
  End Function

  Private Sub DoIt(ByVal param As XElement)
    Dim customers =
      From customer In param...<customer>
      Select New Customer With
      {
        .ID = customer.<id>.Value,
        .FirstName = customer.<name>.Value
      }

    For Each c In customers
      Console.WriteLine(c.ToString())
    Next
  End Sub

  Private Class Customer
    Public ID As Integer
    Public FirstName As String
    Public Overrides Function ToString() As String
      Return <string>
ID : <%= Me.ID %>
Name : <%= Me.FirstName %>
             </string>.Value
    End Function

  End Class
End Module
'Results:

ID : 1
Name : Beth
John
Doe
345: 17
365: 99

Take a look at XML Literals Tips/Tricks by Beth Massi.

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
7

Refined Error Handling using When

Notice the use of when in the line Catch ex As IO.FileLoadException When attempt < 3

Do
  Dim attempt As Integer
  Try
    ''// something that might cause an error.
  Catch ex As IO.FileLoadException When attempt < 3
    If MsgBox("do again?", MsgBoxStyle.YesNo) = MsgBoxResult.No Then
      Exit Do
    End If
  Catch ex As Exception
    ''// if any other error type occurs or the attempts are too many
    MsgBox(ex.Message)
    Exit Do
  End Try
  ''// increment the attempt counter.
  attempt += 1
Loop

Recently viewed in VbRad

Eduardo Molteni
  • 38,786
  • 23
  • 141
  • 206
7

You can have an If in one line.

If True Then DoSomething()
Josh Lee
  • 171,072
  • 38
  • 269
  • 275
Parsa
  • 997
  • 1
  • 15
  • 38
  • 1
    or If x = 0 Then : Do0() : ElseIf x = 1 Then Do1() : Else Do3() : EndIf – Shimmy Weitzhandler Mar 13 '10 at 19:45
  • 1
    @Shimmy yeah, but that's just splitting lines with colons, TRS-80 style. They are syntactically the same as separate lines. But having the whole if-else on one line is neato. – Br.Bill Mar 12 '11 at 00:16
  • 1
    You can do it without the : and without the endif.... Like this.... If a = b then DoThis() else DoThat. And that's it. This even works in vb6 – Erx_VB.NExT.Coder Jan 31 '12 at 02:25
6

Here's a funny one that I haven't seen; I know it works in VS 2008, at least:

If you accidentally end your VB line with a semicolon, because you've been doing too much C#, the semicolon is automatically removed. It's actually impossible (again, in VS 2008 at least) to accidentally end a VB line with a semicolon. Try it!

(It's not perfect; if you type the semicolon halfway through your final class name, it won't autocomplete the class name.)

Ryan Lundy
  • 204,559
  • 37
  • 180
  • 211
6

Unlike break in C languages in VB you can Exit or Continue the block you want to:

For i As Integer = 0 To 100
    While True
        Exit While
        Select Case i
            Case 1
                Exit Select
            Case 2
                Exit For
            Case 3
                Exit While
            Case Else
                Exit Sub
        End Select
        Continue For
    End While
Next
Parsa
  • 997
  • 1
  • 15
  • 38
5

Similar to Parsa's answer, the like operator has lots of things it can match on over and above simple wildcards. I nearly fell of my chair when reading the MSDN doco on it :-)

Community
  • 1
  • 1
Dan F
  • 11,958
  • 3
  • 48
  • 72
5
IIf(False, MsgBox("msg1"), MsgBox("msg2"))

What is the result? two message boxes!!!! This happens cuz the IIf function evaluates both parameters when reaching the function.

VB has a new If operator (just like C# ?: operator):

If(False, MsgBox("msg1"), MsgBox("msg2"))

Will show only second msgbox.

in general I would recommend replacing all the IIFs in you vb code, unless you wanted it to evealueate both items:

Dim value = IIf(somthing, LoadAndGetValue1(), LoadAndGetValue2())

you can be sure that both values were loaded.

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
5

You can use reserved keyword for properties and variable names if you surround the name with [ and ]

Public Class Item
    Private Value As Integer
    Public Sub New(ByVal value As Integer)
        Me.Value = value
    End Sub

    Public ReadOnly Property [String]() As String
        Get
            Return Value
        End Get
    End Property

    Public ReadOnly Property [Integer]() As Integer
        Get
            Return Value
        End Get
    End Property

    Public ReadOnly Property [Boolean]() As Boolean
        Get
            Return Value
        End Get
    End Property
End Class

'Real examples:
Public Class PropertyException : Inherits Exception
    Public Sub New(ByVal [property] As String)
        Me.Property = [property]
    End Sub

    Private m_Property As String
    Public Property [Property]() As String
        Get
            Return m_Property
        End Get
        Set(ByVal value As String)
            m_Property = value
        End Set
    End Property
End Class

Public Enum LoginLevel
    [Public] = 0
    Account = 1
    Admin = 2
    [Default] = Account
End Enum
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
  • Consider that there are also keywords that are Like From Error and more that you might want to use it, I know it's rare, but there are always exceptions. – Shimmy Weitzhandler Jul 14 '09 at 12:17
  • Ok, I take the liberty to edit the answer. Hope you don't mind. – Eduardo Molteni Jul 14 '09 at 22:44
  • 2
    This is a very useful thing to know, actually. Try typing this: `Public Sub Stop` It doesn't work, because Stop is a keyword. The brackets allow you to use Stop as your method name when it makes more sense than another name. – Ryan Lundy Dec 02 '09 at 21:49
5

When declaring an array in vb.net always use the "0 to xx" syntax.

Dim b(0 to 9) as byte 'Declares an array of 10 bytes

It makes it very clear about the span of the array. Compare it with the equivalent

Dim b(9) as byte 'Declares another array of 10 bytes

Even if you know that the second example consists of 10 elements, it just doesn't feel obvious. And I can't remember the number of times when I have seen code from a programmer who wanted the above but instead wrote

Dim b(10) as byte 'Declares another array of 10 bytes

This is of course completely wrong. As b(10) creates an array of 11 bytes. And it can easily cause bugs as it looks correct to anyone who doesn't know what to look for.

The "0 to xx" syntax also works with the below

Dim b As Byte() = New Byte(0 To 9) {} 'Another way to create a 10 byte array
ReDim b(0 to 9) 'Assigns a new 10 byte array to b

By using the full syntax you will also demonstrate to anyone who reads your code in the future that you knew what you were doing.

Marcus Andrén
  • 965
  • 7
  • 9
  • Horrors! the "to" keyword isn't capitalized! ;) – RCIX Nov 27 '09 at 07:18
  • 1
    VB.NET keywords are case insensitive actually. :) Not sure if that counts as a hidden feature. – Marcus Andrén Nov 27 '09 at 08:59
  • 2
    The fact that Dim b(9) as byte creates an array with 10 places drives me mad. I understand why Microsoft did it, but that doesn't mean it was a good decision (and I say this as someone who likes VB .NET). Of course, it's not as awful as it could be because for most things I use collections instead of arrays anyhow. – Ryan Lundy Dec 02 '09 at 21:46
  • Vb.net array initializer counter is zero-based. – Shimmy Weitzhandler Jul 11 '10 at 00:57
  • BTW, you can also include n To f Step x in case you want to dynamically generate an array according to some content. – Shimmy Weitzhandler Jul 11 '10 at 00:59
5

In VB8 and the former vesions, if you didn't specify any type for the variable you introduce, the Object type was automaticly detected. In VB9 (2008), the Dim would act like C#'s var keyword if the Option Infer is set to On (which is, by default)

Parsa
  • 997
  • 1
  • 15
  • 38
  • 4
    ALWAYS set Option Explicit. You can use Tools-Options to insert this automatically in all new source files. – MarkJ Jun 09 '09 at 14:44
  • 1
    It's automatically set in the project properties by default, unless you're still working with VB 6 or older – Parsa Jun 09 '09 at 18:41
  • 3
    I believe it's actually Option Strict, not Option Explicit, which prevents you from typing Dim i and getting an Object type. It forces you to type As Object if you really want an object. Even with Option Infer on, it's best to have Option Strict (and Option Explicit) turned on as well. – Ryan Lundy Aug 06 '09 at 21:21
5

Select Case in place of multiple If/ElseIf/Else statements.

Assume simple geometry objects in this example:

Function GetToString(obj as SimpleGeomertyClass) as String
  Select Case True
    Case TypeOf obj is PointClass
      Return String.Format("Point: Position = {0}", _
                            DirectCast(obj,Point).ToString)
    Case TypeOf obj is LineClass
      Dim Line = DirectCast(obj,LineClass)
      Return String.Format("Line: StartPosition = {0}, EndPosition = {1}", _
                            Line.StartPoint.ToString,Line.EndPoint.ToString)
    Case TypeOf obj is CircleClass
      Dim Line = DirectCast(obj,CircleClass)
      Return String.Format("Circle: CenterPosition = {0}, Radius = {1}", _
                            Circle.CenterPoint.ToString,Circle.Radius)
    Case Else
      Return String.Format("Unhandled Type {0}",TypeName(obj))
  End Select
End Function
  • 3
    There is a switch in C#, and that is an abomination – Rulas Aug 18 '09 at 22:04
  • Haha, I've used this quite extensively, and my method became about 300 lines long in about 20 minutes. – dance2die Oct 20 '09 at 02:41
  • 2
    I can't fathom what would make people think that `Select Case True` is better than a plain old `If`. If you're using it like an `If`, just make it an `If`. Why obfuscate? – Ryan Lundy Dec 02 '09 at 21:52
  • @Kyralessa, I think it is the aesthetic of all of the conditions being indented the same. However another reason it occurs is when a Select Case Expression evolves and the Case Else becomes another large conditional. – Mark Hurd Apr 03 '10 at 05:38
  • 1
    @Kyralessa, what if the types have nothing in common such as Int32, Date, and String? Polymorphism only works when you control over class's definitions. – Jonathan Allen Jul 18 '10 at 11:53
  • What is REALLY important to understand regarding Select-Case is this: ANY time you have to add another case, you end up altering code that was already known to work and now have to test it completely again. Your code should always try following the Open-Closed-Principle: Open to extension, Closed to changes. Design your classes so that they can be extended without having to change their implementation. For example the strategy pattern can be used to refactor a Select-Case statement to something that allows you to follow the O/C principle. – Mephisztoe Aug 06 '10 at 13:52
  • 1
    @Mephisztoe: The same goes for a repetitive-looking if/else/else/else/... statement. What you're really saying here is write good smart code. yes, I agree with _that_. – Br.Bill Mar 12 '11 at 00:21
4

It is also important to remember that VB.NET projects, by default, have a root namespace that is part of the project’s properties. By default this root namespace will have the same name as the project. When using the Namespace block structure, Names are actually appended to that root namespace. For example: if the project is named MyProject, then we could declare a variable as:

Private obj As MyProject.MyNamespace.MyClass

To change the root namespace, use the Project -> Properties menu option. The root namespace can be cleared as well, meaning that all Namespace blocks become the root level for the code they contain.

Nescio
  • 27,645
  • 10
  • 53
  • 72
  • This has bitten us in a few cases where we added further namespaces inside the project. In a few cases we have the "My" keyword under one of our namespaces; which makes finding Resources a pain until you realize where they've been moved to :) – STW May 05 '09 at 14:41
4

Unlike in C#, in VB you can rely on the default values for non-nullable items:

Sub Main()
    'Auto assigned to def value'
    Dim i As Integer '0'
    Dim dt As DateTime '#12:00:00 AM#'
    Dim a As Date '#12:00:00 AM#'
    Dim b As Boolean 'False'

    Dim s = i.ToString 'valid
End Sub

Whereas in C#, this will be a compiler error:

int x;
var y = x.ToString(); //Use of unassigned value
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
4

The Nothing keyword can mean default(T) or null, depending on the context. You can exploit this to make a very interesting method:

'''<summary>Returns true for reference types, false for struct types.</summary>'
Public Function IsReferenceType(Of T)() As Boolean
    Return DirectCast(Nothing, T) Is Nothing
End Function
Craig Gidney
  • 17,763
  • 5
  • 68
  • 136
  • 2
    +1 for the nice hack but not terribly useful since .NET provides the same information by querying the `GetType(T).IsValueType` property. – Konrad Rudolph Sep 19 '09 at 07:39
4

may be this link should help

http://blogs.msdn.com/vbteam/archive/2007/11/20/hidden-gems-in-visual-basic-2008-amanda-silver.aspx

4

MyClass keyword provides a way to refer to the class instance members as originally implemented, ignoring any derived class overrides.

Parsa
  • 997
  • 1
  • 15
  • 38
3

Aliassing namespaces

Imports Lan = Langauge

Although not unique to VB.Net it is often forgotten when running into namespace conflicts.

chrissie1
  • 5,014
  • 3
  • 26
  • 26
3

VB also offers the OnError statement. But it's not much of use these days.

On Error Resume Next
' Or'
On Error GoTo someline

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
Parsa
  • 997
  • 1
  • 15
  • 38
  • @SungMeister, I like the power exceptions provide and do use them in new code, but for the (few) situations where `On Error Resume Next` is the right thing, it is *much* less cluttered than Try Catch on every statement. – Mark Hurd Apr 03 '10 at 05:41
  • @Mark Hud: But sometimes limiting what one can use can discourage bad coding practices. I have seen too many `ON ERROR RESUME NEXT` or `ON ERROR GOTO 1`'s when people are under time pressure. Leaving such a feature for the sake of very few specialized cases that can be solved through a bit verbose way, IMHO, cannot be justified. But Alas, it is for a backward compatibility purposes AFAIK. – dance2die Apr 03 '10 at 14:59
  • @Sung Meister: yeah, but if they do, how will I quickly port all my awzzum old QuickBasic programs? – Br.Bill Mar 12 '11 at 00:26
2

I don't know how hidden you'd call it, but the If operator could count.

It's very similar, in a way, to the ?: (ternary) or the ?? operator in a lot of C-like languages. However, it's important to note that it does evaluate all of the parameters, so it's important to not pass in anything that may cause an exception (unless you want it to) or anything that may cause unintended side-effects.

Usage:

Dim result = If(condition, valueWhenTrue, valueWhenFalse)
Dim value = If(obj, valueWhenObjNull)
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Sam Erwin
  • 335
  • 1
  • 12
2

You can use REM to comment out a line instead of ' . Not super useful, but helps important comments standout w/o using "!!!!!!!" or whatever.

Booji Boy
  • 4,522
  • 4
  • 40
  • 45
  • 5
    Notice, however, that usage of `REM` is deprecated. The VB team is considering removing it from the next version altogether. Future-proof code is therefore better off not employing it. – Konrad Rudolph Sep 19 '08 at 16:07
  • 1
    True, but they haven't they been saying that since VB5? – Oorang May 22 '09 at 19:57
  • I don't they will ever remove it – Shimmy Weitzhandler Jul 17 '09 at 11:41
  • Wow... REM... It's been awhile! I don't think I've used REM since the Apple ][c – Brad Nov 05 '10 at 13:25
  • @KonradRudolph @Oorang: Link please. Googling for 'vb.net REM "depreciated" site:microsoft.com' finds nothing. – Mark Hurd May 19 '11 at 16:43
  • @Mark No link available (wayback machine might work) since the source of my information is Paul Vick’s blog (from when he headed the VB team), which he has since scrubbed. – Konrad Rudolph May 19 '11 at 17:35
  • @KonradRudolph: Google 'REM site:panopticoncentral.net' returns exactly one page where the Google cache shows Paul mention in a comment that REM "still works, even in VB.NET!" – Mark Hurd May 19 '11 at 19:15
  • @Mark Then Google hasn’t indexed all pages, or the cache has dropped them. I’m certain that this *was* discussed on the site. – Konrad Rudolph May 19 '11 at 19:22
2
Private Sub Button1_Click(ByVal sender As Button, ByVal e As System.EventArgs)
        Handles Button1.Click
    sender.Enabled = True
    DisableButton(sender)
End Sub

Private Sub Disable(button As Object)
    button.Enabled = false
End Sub

In this snippet you have 2 (maybe more?) things that you could never do in C#:

  1. Handles Button1.Click - attach a handler to the event externally!
  2. VB's implicitness allows you to declare the first param of the handler as the expexted type. in C# you cannot address a delegate to a different pattern, even it's the expected type.

Also, in C# you cannot use expected functionality on object - in C# you can dream about it (now they made the dynamic keyword, but it's far away from VB). In C#, if you will write (new object()).Enabled you will get an error that type object doesn't have a method 'Enabled'. Now, I am not the one who will recommend you if this is safe or not, the info is provided AS IS, do on your own, bus still, sometimes (like when working with COM objects) this is such a good thing. I personally always write (sender As Button) when the expected value is surely a button.

Actually moreover: take this example:

Private Sub control_Click(ByVal sender As Control, ByVal e As System.EventArgs)
        Handles TextBox1.Click, CheckBox1.Click, Button1.Click
    sender.Text = "Got it?..."
End Sub
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
  • 3
    Your examples only work with Option Strict Off. And Option Strict Off is a Bad Thing, because it leads to runtime errors if you misspell the name of the late-bound members you're using. – Ryan Lundy Aug 06 '09 at 21:38
  • 1
    Strict off is the advantage of VB. To each is own taste, every thing has it's own pros and cons. – Shimmy Weitzhandler Oct 19 '09 at 15:35
  • 1
    @Kyralessa, While I usually with you, there are some amazing Function Programming techniques that can't do with option strict turned on. In fact, they are outright impossible in C# even with `dynamic`. – Jonathan Allen Jul 18 '10 at 11:49
2

Nullable Dates! This is particularly useful in cases where you have data going in / coming out of a database (in this case, MSSQL Server). I have two procedures to give me a SmallDateTime parameter, populated with a value. One of them takes a plain old date and tests to see if there's any value in it, assigning a default date. The other version accepts a Nullable(Of Date) so that I can leave the date valueless, accepting whatever the default was from the stored procedure

<System.Diagnostics.DebuggerStepThrough> _
Protected Function GP(ByVal strName As String, ByVal dtValue As Date) As SqlParameter
    Dim aParm As SqlParameter = New SqlParameter
    Dim unDate As Date
    With aParm
        .ParameterName = strName
        .Direction = ParameterDirection.Input
        .SqlDbType = SqlDbType.SmallDateTime
        If unDate = dtValue Then    'Unassigned variable
            .Value = "1/1/1900 12:00:00 AM" 'give it a default which is accepted by smalldatetime
        Else
            .Value = CDate(dtValue.ToShortDateString)
        End If
    End With
    Return aParm
End Function
<System.Diagnostics.DebuggerStepThrough()> _
Protected Function GP(ByVal strName As String, ByVal dtValue As Nullable(Of Date)) As SqlParameter
    Dim aParm As SqlParameter = New SqlParameter
    Dim unDate As Date
    With aParm
        .ParameterName = strName
        .Direction = ParameterDirection.Input
        .SqlDbType = SqlDbType.SmallDateTime
        If dtValue.HasValue = False Then
            '// it's nullable, so has no value
        ElseIf unDate = dtValue.Value Then    'Unassigned variable
            '// still, it's nullable for a reason, folks!
        Else
            .Value = CDate(dtValue.Value.ToShortDateString)
        End If
    End With
    Return aParm
End Function
David T. Macknet
  • 3,112
  • 3
  • 27
  • 36
2

It's not possible to Explicitly implement interface members in VB, but it's possible to implement them with a different name.

Interface I1
    Sub Foo()
    Sub TheFoo()
End Interface

Interface I2
    Sub Foo()
    Sub TheFoo()
End Interface

Class C
    Implements I1, I2

    Public Sub IAmFoo1() Implements I1.Foo
        ' Something happens here'
    End Sub

    Public Sub IAmFoo2() Implements I2.Foo
        ' Another thing happens here'
    End Sub

    Public Sub TheF() Implements I1.TheFoo, I2.TheFoo
        ' You shouldn't yell!'
    End Sub
End Class

Please vote for this feature at Microsoft Connect.

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Parsa
  • 997
  • 1
  • 15
  • 38
  • 2
    I think you mean _implicitly_ – Eric Nicholson Jan 05 '10 at 19:32
  • @Eric: No, explicitly implementing is a feature available in C# which makes the explicitly implemented method unavailable to instanced of the class directly and if you want to call them you must cast your class to the interface type. Take a look at http://msdn.microsoft.com/en-us/library/ms173157%28loband%29.aspx – Parsa Jan 06 '10 at 08:27
  • @Jonathan Allen: Can't figure why? – Parsa Jul 20 '10 at 05:47
  • Consider `IEnumerable.GetEnumerator` and `IEnumerable(Of T).GetEnumerator`. If you expose the generic version, there is no reason to also expose the non-generic version. – Jonathan Allen Jul 20 '10 at 06:12
  • Please vote for this feautre: https://connect.microsoft.com/VisualStudio/feedback/details/454529/allow-implicit-interface-implementation-in-vb-like-in-c – Shimmy Weitzhandler Nov 10 '10 at 02:56
  • 1
    @Jonthan it always freaks me out, anyway, if you declare them both as `Overloads`, it's possible. – Shimmy Weitzhandler Dec 30 '10 at 22:43
1

I used to be very fond of optional function parameters, but I use them less now that I have to go back and forth between C# and VB a lot. When will C# support them? C++ and even C had them (of a sort)!

Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • I was never a fan, but your answer prompted me to dig into them a bit and see what they looked like under the hood. You may be interested in [How do optional parameters work?][1] [1] http://stackoverflow.com/questions/104068/how-do-optional-parameters-in-vbnet-work – John Rudy Sep 19 '08 at 17:59
  • 2
    Optional parameters and named parameters will be in the next version of C#. – codeConcussion Nov 06 '08 at 19:14
  • 3
    although they are generally considered bad practice; use overloaded methods instead. – Pondidum Dec 26 '08 at 20:12
  • 3
    Agreed on overloads, but you can't overload when you're doing COM Interop, so you have to use the optionals - and named parameters are vital when you're doing Interop into Office, where the methods have 30-40 optional parameters. – Richard Gadsden Feb 09 '09 at 12:42
  • 1
    optional params are now supported in C#! – Shimmy Weitzhandler Dec 30 '10 at 18:22
1

Differences between ByVal and ByRef keywords:

Module Module1

    Sub Main()
        Dim str1 = "initial"
        Dim str2 = "initial"
        DoByVal(str1)
        DoByRef(str2)

        Console.WriteLine(str1)
        Console.WriteLine(str2)
    End Sub

    Sub DoByVal(ByVal str As String)
        str = "value 1"
    End Sub

    Sub DoByRef(ByRef str As String)
        str = "value 2"
    End Sub
End Module

'Results:
'initial
'value 2
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
  • Except that, unfortunately, this doesn't work with collections - try passing a collection in ByVal and then removing an item from it in your sub - you'll find that it's been removed from the original as well :( – SqlRyan Nov 05 '10 at 17:04
  • It works with collection too. Because when you cange a collection, you don't change the instance itself, you just change the internal propetries of it. and if you want to see it yourself, try a method that has a ByVal param of c of type collection, set it to a new collection within the method, and you'll see that the argument doesn't contain your new collection outside the method scope, unlike when it's ByRef. – Shimmy Weitzhandler Nov 10 '10 at 02:51
  • @rwmnau, collections are reference types. Whether you use ByVal or ByRef, you're pointing to the original collection. The difference is that if *inside the method* you point your variable to a different collection or to null, then when you return from the method, if you used ByVal you'll still be pointing to the original collection; but if you used ByRef you'll be pointing to the new collection or to null, whatever you reassigned to inside the method. TL;DR: Use ByRef as infrequently as possible. And if you need a copy of a collection, then *explicitly* copy it; ByRef doesn't do that. – Ryan Lundy Dec 30 '11 at 19:07
1

Someday Basic users didn't introduce any variable. They introduced them just by using them. VB's Option Explicit was introduced just to make sure you wouldn't introduce any variable mistakenly by bad typing. You can always turn it to Off, experience the days we worked with Basic.

Parsa
  • 997
  • 1
  • 15
  • 38
1

Documentation of code

''' <summary>
''' 
''' </summary>
''' <remarks></remarks>
Sub use_3Apostrophe()
End Sub
PdotWang
  • 147
  • 1
  • 3
0
Sub Main()
    Select Case "value to check"
        'Check for multiple items at once:'
        Case "a", "b", "asdf" 
            Console.WriteLine("Nope...")
        Case "value to check"
            Console.WriteLine("Oh yeah! thass what im talkin about!")
        Case Else
            Console.WriteLine("Nah :'(")
    End Select


    Dim jonny = False
    Dim charlie = True
    Dim values = New String() {"asdff", "asdfasdf"}
    Select Case "asdfasdf"
        'You can perform boolean checks that has nothing to do with your var.,
        'not that I would recommend that, but it exists.'
        Case values.Contains("ddddddddddddddddddddddd")
        Case True
        Case "No sense"
        Case Else
    End Select

    Dim x = 56
    Select Case x
        Case Is > 56
        Case Is <= 5
        Case Is <> 45
        Case Else
    End Select

End Sub
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632
0

Attributes for methods! For example, a property which shouldn't be available during design time can be 1) hidden from the properties window, 2) not serialized (particularly annoying for user controls, or for controls which are loaded from a database):

<System.ComponentModel.Browsable(False), _
System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden), _
System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Always), _
System.ComponentModel.Category("Data")> _
Public Property AUX_ID() As String
    <System.Diagnostics.DebuggerStepThrough()> _
     Get
        Return mAUX_ID
    End Get
    <System.Diagnostics.DebuggerStepThrough()> _
     Set(ByVal value As String)
        mAUX_ID = value
    End Set
End Property

Putting in the DebuggerStepThrough() is also very helpful if you do any amount of debugging (note that you can still put a break-point within the function or whatever, but that you can't single-step through that function).

Also, the ability to put things in categories (e.g., "Data") means that, if you do want the property to show up in the properties tool-window, that particular property will show up in that category.

David T. Macknet
  • 3,112
  • 3
  • 27
  • 36
0

Optional arguments again !

Function DoSmtg(Optional a As string, b As Integer, c As String)
    'DoSmtg
End 

' Call
DoSmtg(,,"c argument")

DoSmtg(,"b argument")
-3

The Me Keyword

The "Me" Keyword is unique in VB.Net. I know it is rather common but there is a difference between "Me" and the C# equivalent "this". The difference is "this" is read only and "Me" is not. This is valuable in constructors where you have an instance of a variable you want the variable being constructed to equal already as you can just set "Me = TheVariable" as opposed to C# where you would have to copy each field of the variable manually(which can be horrible if there are many fields and error prone). The C# workaround would be to do the assignment outside the constructor. Which means you now if the object is self-constructing to a complete object you now need another function.

swight
  • 1
  • 1
    Yup, it'll give you a compile error - `'Me' cannot be the target of an assignment` – Adam Neal Jun 04 '10 at 13:05
  • 1
    Actually, `this` in C# **is not** always readonly; inside a `struct` it can be assigned. Maybe @swight is referring to VB structs? Perhaps? Just possibly? Probably not, actually. – Marc Gravell Nov 10 '10 at 06:49