Hidden Features of VB.NET?

vb.netHidden Features

vb.net Problem Overview


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?

vb.net Solutions


Solution 1 - vb.net

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

Solution 2 - vb.net

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

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

Solution 3 - vb.net

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*"

Solution 4 - vb.net

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)

Solution 5 - vb.net

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>

Solution 6 - vb.net

Object initialization is in there too!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}

Solution 7 - vb.net

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

Solution 8 - vb.net

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)

Solution 9 - vb.net

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

Solution 10 - vb.net

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!

Solution 11 - vb.net

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#

Solution 12 - vb.net

  • AndAlso/OrElse logical operators

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

Solution 13 - vb.net

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.

Solution 14 - vb.net

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

Solution 15 - vb.net

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

Solution 16 - vb.net

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.

Solution 17 - vb.net

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.

Solution 18 - vb.net

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

Solution 19 - vb.net

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

Solution 20 - vb.net

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

Solution 21 - vb.net

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

Solution 22 - vb.net

Import aliases are also largely unknown:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form

Solution 23 - vb.net

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

Solution 24 - vb.net

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

Solution 25 - vb.net

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

Solution 26 - vb.net

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

Dim x As New Something : x.CallAMethod

Solution 27 - vb.net

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)

Solution 28 - vb.net

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

Solution 29 - vb.net

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

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID

Solution 30 - vb.net

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: https://stackoverflow.com/questions/236530/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

Solution 31 - vb.net

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.

Solution 32 - vb.net

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)

Solution 33 - vb.net

  • 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.

Solution 34 - vb.net

You can have an If in one line.

If True Then DoSomething()

Solution 35 - vb.net

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.

Solution 36 - vb.net

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

Solution 37 - vb.net

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

Solution 38 - vb.net

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

Solution 39 - vb.net

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)

Solution 40 - vb.net

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

Solution 41 - vb.net

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

Solution 42 - vb.net

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.

Solution 43 - vb.net

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

Solution 44 - vb.net

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.

Solution 45 - vb.net

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.

Solution 46 - vb.net

Solution 47 - vb.net

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

Solution 48 - vb.net

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

Solution 49 - vb.net

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

Solution 50 - vb.net

Aliassing namespaces

Imports Lan = Langauge

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

Solution 51 - vb.net

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

On Error Resume Next
' Or'
On Error GoTo someline

Solution 52 - vb.net

I don't know how hidden you'd call it, but the [If][1] 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)

[1]: http://msdn.microsoft.com/en-us/library/bb513985.aspx "If Operator (Visual Basic)"

Solution 53 - vb.net

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

Solution 54 - vb.net

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](https://connect.microsoft.com/VisualStudio/feedback/details/454529/allow-implicit-interface-implementation-in-vb-like-in-c "Allow implicit interface implementation in VB like in C#").

Solution 55 - vb.net

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

Solution 56 - vb.net

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

Solution 57 - vb.net

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

Solution 58 - vb.net

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.

Solution 59 - vb.net

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

Solution 60 - vb.net

Documentation of code

''' <summary>
''' 
''' </summary>
''' <remarks></remarks>
Sub use_3Apostrophe()
End Sub

Solution 61 - vb.net

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

Solution 62 - vb.net

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.

Solution 63 - vb.net

Optional arguments again !

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

' Call
DoSmtg(,,"c argument")

DoSmtg(,"b argument")

Solution 64 - vb.net

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSean GoughView Question on Stackoverflow
Solution 1 - vb.nettorialView Answer on Stackoverflow
Solution 2 - vb.netKonrad RudolphView Answer on Stackoverflow
Solution 3 - vb.netParsaView Answer on Stackoverflow
Solution 4 - vb.netKonrad RudolphView Answer on Stackoverflow
Solution 5 - vb.netNescioView Answer on Stackoverflow
Solution 6 - vb.netNescioView Answer on Stackoverflow
Solution 7 - vb.netKonrad RudolphView Answer on Stackoverflow
Solution 8 - vb.netKonrad RudolphView Answer on Stackoverflow
Solution 9 - vb.nettorialView Answer on Stackoverflow
Solution 10 - vb.netJasha87View Answer on Stackoverflow
Solution 11 - vb.netcjkView Answer on Stackoverflow
Solution 12 - vb.netJoel CoehoornView Answer on Stackoverflow
Solution 13 - vb.netJoel CoehoornView Answer on Stackoverflow
Solution 14 - vb.netShimmy WeitzhandlerView Answer on Stackoverflow
Solution 15 - vb.netKonrad RudolphView Answer on Stackoverflow
Solution 16 - vb.netsplattneView Answer on Stackoverflow
Solution 17 - vb.nettorialView Answer on Stackoverflow
Solution 18 - vb.nettorialView Answer on Stackoverflow
Solution 19 - vb.netChris HaasView Answer on Stackoverflow
Solution 20 - vb.netRichView Answer on Stackoverflow
Solution 21 - vb.nettorialView Answer on Stackoverflow
Solution 22 - vb.nettorialView Answer on Stackoverflow
Solution 23 - vb.nettorialView Answer on Stackoverflow
Solution 24 - vb.netTechnobabbleView Answer on Stackoverflow
Solution 25 - vb.netRyan LundyView Answer on Stackoverflow
Solution 26 - vb.netParsaView Answer on Stackoverflow
Solution 27 - vb.netdanlashView Answer on Stackoverflow
Solution 28 - vb.netdr. evilView Answer on Stackoverflow
Solution 29 - vb.nettorialView Answer on Stackoverflow
Solution 30 - vb.nettorialView Answer on Stackoverflow
Solution 31 - vb.netJoel CoehoornView Answer on Stackoverflow
Solution 32 - vb.netYoussefView Answer on Stackoverflow
Solution 33 - vb.netJoel CoehoornView Answer on Stackoverflow
Solution 34 - vb.netParsaView Answer on Stackoverflow
Solution 35 - vb.netShimmy WeitzhandlerView Answer on Stackoverflow
Solution 36 - vb.netEduardo MolteniView Answer on Stackoverflow
Solution 37 - vb.netRyan LundyView Answer on Stackoverflow
Solution 38 - vb.netParsaView Answer on Stackoverflow
Solution 39 - vb.netParsaView Answer on Stackoverflow
Solution 40 - vb.netClifView Answer on Stackoverflow
Solution 41 - vb.netDan FView Answer on Stackoverflow
Solution 42 - vb.netShimmy WeitzhandlerView Answer on Stackoverflow
Solution 43 - vb.netShimmy WeitzhandlerView Answer on Stackoverflow
Solution 44 - vb.netMarcus AndrénView Answer on Stackoverflow
Solution 45 - vb.netNescioView Answer on Stackoverflow
Solution 46 - vb.netView Answer on Stackoverflow
Solution 47 - vb.netParsaView Answer on Stackoverflow
Solution 48 - vb.netShimmy WeitzhandlerView Answer on Stackoverflow
Solution 49 - vb.netCraig GidneyView Answer on Stackoverflow
Solution 50 - vb.netchrissie1View Answer on Stackoverflow
Solution 51 - vb.netParsaView Answer on Stackoverflow
Solution 52 - vb.netSam ErwinView Answer on Stackoverflow
Solution 53 - vb.netBooji BoyView Answer on Stackoverflow
Solution 54 - vb.netParsaView Answer on Stackoverflow
Solution 55 - vb.netShimmy WeitzhandlerView Answer on Stackoverflow
Solution 56 - vb.netDavid T. MacknetView Answer on Stackoverflow
Solution 57 - vb.netJoel CoehoornView Answer on Stackoverflow
Solution 58 - vb.netParsaView Answer on Stackoverflow
Solution 59 - vb.netShimmy WeitzhandlerView Answer on Stackoverflow
Solution 60 - vb.netPdotWangView Answer on Stackoverflow
Solution 61 - vb.netShimmy WeitzhandlerView Answer on Stackoverflow
Solution 62 - vb.netDavid T. MacknetView Answer on Stackoverflow
Solution 63 - vb.netHedi GuizaniView Answer on Stackoverflow
Solution 64 - vb.netswightView Answer on Stackoverflow