views:

7529

answers:

62

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?

+22  A: 
  • AndAlso/OrElse logical operators

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

Joel Coehoorn
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
+23  A: 

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
Agreed on this... much more readable and promotes the good kind of laziness.
Mike L
But it also create some hidden bugs, especially when you have With within With
Varun Mahajan
I'm still not comfortable using it.
Matias Nino
I didn't even know you could put a new With within an existing With. That's just sloppy!
Bob King
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
Wish C# has this? Or have I been asleep and is that in the C# hidden-features answers already...? ;-)
peSHIr
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
@Romias: wrong. The debugger can indeed show the value of a with block member in a hover-over.
Boo
@Boo: You're right but it's still an annoyance that you can't add it to the Watch list.
Meta-Knight
This is a cool thingy that C# does not have!
Shimmy
This is one of my pet hates! Aweful code!
Stevo3000
+2  A: 

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 very similar, in a way, to the ? : (ternary) 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.

Sam Erwin
Also, it's return type is Object. I use my own typesafe IIf(Of T) implementation.
Joel Coehoorn
VB9 now has a If that *is* ternay operator just like the ?: in C
Rick
I see that. It makes me sad that I don't get to use VB9 at work right now.
Sam Erwin
IIF is also unmanaged i believe.
Pondidum
@Rick: Really? What operator would that be?
Boo
@Boo: Rick actually used the actual name of the new operator. It is "If" as opposed to "Iif" (one fewer "i"). The difference is that "Iif" evaluates all of its arguments but "If" evaluates just the ones it needs to.
Ray Burns
+5  A: 
  • 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
I just hate this *feature* since I get lost without looking at namespace in the beginning of the file... but still +1!
Sung Meister
+31  A: 

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)
Konrad Rudolph
Nice, I didn't know this! I just used IIF yesterday so I'm going to revisit that code block.
Sean Gough
Nice to know. It's not exactly deprecated, though, if your job has you targeting the 2.0 framework.
Sam Erwin
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
Tell VS 2005 that. Not all of us get to work with the latest and greatest.
Sam Erwin
Only and huuuge problem with this it's not type-safety, it returns and object which is rubbish 99% of the time.
dr. evil
@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
Yes, its IIf() that is not type safe
Pondidum
+101  A: 

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
torial
That was very big secret.
chrissie1
On my, I like this one.
Sean Gough
Me too - good answer.
Brian MacKay
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
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
+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
Not only is this hidden, but it is also not available in C#.
Cheeso
+34  A: 

Object initialization is in there too!

Dim x as New MyClass With {.Prop1 = foo, .Prop2 = bar}
Nescio
Curly braces have finally reached VB ;-)
Enrico Campidoglio
I can't believe they went with curly braces. We already have a With statement.. they could have just reused that syntax.
Boo
I know, it's made just to show you that there is no cop on the road...lol JK
Shimmy
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
I had NO IDEA! This will save me a lot of time.
Brad
+1  A: 

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

Joel Coehoorn
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
Optional parameters and named parameters will be in the next version of C#.
whatknott
although they are generally considered bad practice; use overloaded methods instead.
Pondidum
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
+8  A: 

Import aliases are also largely unknown:

Import winf = System.Windows.Forms

''Later
Dim x as winf.Form
torial
I think we had the same idea.
chrissie1
YUCK YUCK YUCK!! Import aliases are EVIL. They make your code less maintainable and less readable. I'd fire your ass if you worked for me.
Boo
Glad I don't work for you!
torial
@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
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
+66  A: 
Konrad Rudolph
Wow, I didn't know you could do this!
Nescio
Yeah this is cool.
torial
Interesting - could you show an example of how this looks when you consume it?
Brian MacKay
Wow, that's awesome!
Jonathan Allen
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
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
Wow didn't know this one, really cool!
dr. evil
Nice job Konrad
Boo
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
@Maslow: there's not attribute involved here. That is an xml comment.
Joel Coehoorn
@Joel: please enlighten me: how did you prevent highlighting the comment?
Konrad Rudolph
You can also make a class its own completion list.
Daniel Straight
wooooooooooooow!
Shimmy
Definately a nice bonus when combined with the Strategy pattern (as your example shows)
STW
...although I just noticed it doesn't work for generics with a Type constraint (small sad face). So *SomeMethod(Of T as Rule)()* won't show the dialog
STW
+11  A: 

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
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
Definately one of my favorites as well.
Boo
+3  A: 

Aliassing namespaces

Imports Lan = Langauge

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

chrissie1
Can you do this declaritively as well?
EdenMachine
+3  A: 

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
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
+15  A: 

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
Im pritty sure that you can do something like this in C#. In VB.NET its just forced, and in C# its optional?
Jesper Blad Jensen aka. Deldy
Not sure if it is such a good idea... but its a feature :)
Romias
You can also make the sub private, which is a great way to hide stuff like the calls to non-generic deprecated versions of interfaces.
Strilanc
It can be a good idea. The classic example would be if you want a Public Close method that also acts as your Dispose implementation for IDisposable.
MarkJ
That's also pretty useful if you happen to implement two interfaces that share a method name.
Eric Nicholson
I've seen this and always wish I hadn't. Should not be allowed.
FastAl
+33  A: 

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
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
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: `<string>This string contains "quotes" and it's OK.</string>.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.)
Kyralessa
@Kyralessa: +1, great comment. In fact, it's also a great way to specify multi-line strings (hugs SQL statements, etc.).
Heinzi
+40  A: 

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
please show an example the word Import is unrecognized in my IDE.
Shimmy
`Imports` it should be. ;-) Somehow, this error has gone undetected (and garnered 28 upvotes) for nearly a whole year.
Konrad Rudolph
I always wondered how i could make a new "type" with defaults for a generic! Cool!
eidylon
Import, Imports, Importz, whatever! Sheesh, you think we *read* these posts before we upvote them!
MarkJ
Superb for using xunit in visual studio tests i.e. `Imports Assert = xUnit.Assert`
wheelibin
A: 

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
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
True, but they haven't they been saying that since VB5?
Oorang
I don't they will ever remove it
Shimmy
+12  A: 

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
eeck, yeah gross
chrissie1
I think this example would be better if you didn't use "If" as the example keyword.
Sean Gough
Agreed.. I think this works better.
torial
timer.Start and timer.Stop spring to mind as examples of good use of this
Pondidum
+1 for pointing it out with a disclaimer. There are several framework classes that require this to resolve correctly, such as [Assembly]
STW
[Enum] is another good example of a case where you need the brackets in order to use the class instead of the keyword.
Kyralessa
+6  A: 

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

StrConv(stringToTitleCase, VbStrConv.ProperCase,0) ''0 is localeID
torial
its also in the textinfo class. not sure what namespace that is in. probably system.text
Shawn Simon
+29  A: 

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

Konrad Rudolph
Zack, thanks for the link.
Konrad Rudolph
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
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
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
Apparently tryCast doesn't work with Enums
Maslow
@Maslow: of course it doesn't, since Enums are value types and `TryCast` only works on reference types, as per the documentation.
Konrad Rudolph
+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
+11  A: 

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
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
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
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
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
+19  A: 

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
Konrad Rudolph
seems cool, but if I ever need this I think I will have done something wrong ;-). It just seems against the KISS principle.
chrissie1
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
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
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
+18  A: 

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
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.
Kyralessa
This is the reason why static class members are named "shared" in VB.NET
Enrico Campidoglio
Static is bad form in VB.NET even more than it was in classic VB. Static variables should be avoided whenever and wherever possible.
Boo
@Boo - that's pretty sweeping. What's your justification? I think static variables are useful.
MarkJ
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.
Kyralessa
@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
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
+19  A: 

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
This is just great and every vb.net guy out there should know stuff in My namespace, it's so useful.
dr. evil
My.* FTW :) .
dr. evil
It's sort of useful, but I hate the dumbed down name. Reminds me of this http://www.secretgeek.net/refactvb.asp
MarkJ
Can you please decipher what's FTW???
Shimmy
FTW = For the Win! http://www.urbandictionary.com/define.php?term=ftw
splattne
+4  A: 

may be this link should help

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

upvoted - nice link
Maslow
+9  A: 

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
dr. evil
it is so good that the next version of C# will get it!
torial
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
...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
Ah, I despise this so much... But useful for Office automation
Sung Meister
+13  A: 

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")
rich
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.
EdenMachine
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
Especially useful for Office automation, where you have to cope with methods with dozens of optional arguments.
MarkJ
C# doesn't have it!
Shimmy
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
@Shimmy: C# 4 does :)
RCIX
+8  A: 

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: http://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
torial
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
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
+26  A: 

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
torial
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
Please don't use Select Case True. Just use an If statement.
Kyralessa
+1  A: 
Parsa
I think you mean _implicitly_
Eric Nicholson
@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
@Parsa Just mark the methods as `Private`.
Jonathan Allen
@Jonathan Allen: Can't figure why?
Parsa
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
+10  A: 

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

Dim x As New Something : x.CallAMethod
Parsa
whoa... i thought this was only possible w/class and inheritance
Jason
Don't forget `Call (New Something).CallAMethod()`
Jonathan Allen
This is a holdever from MS-Basic on the Apple ][! In my shop I would be just as ridiculed for using Gotos :-/
FastAl
+5  A: 

You can have an If in one line.

If True Then DoSomething()
Parsa
and the else also.
xpda
or If x = 0 Then : Do0() : ElseIf x = 1 Then Do1() : Else Do3() : EndIf
Shimmy
+3  A: 
Parsa
+1: they gotta kill this one.
Sung Meister
@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
@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.
Sung Meister
+32  A: 
Parsa
wait, what? That's new to me! Hmm, that's a helluva lot better than the alternative with VB.NET string manipulation :D
STW
..!! I didn't know that although I worked on several vb.net projects! Interesting feature...
Meta-Knight
woooooooooooooooooooooooow!thanks!that's awsome!does it work in ELinq, DLinq too? what about XLinq?
Shimmy
+1very nice feature
Rulas
like a lazy man's regex, pun intended
dotjoe
@dotjoe Hmm? There's nothing 'lazy' about these globs.
jleedev
How does this perform, whats happening under the hood? Is it s synonym for reg ex libraries?
brumScouse
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
+1  A: 

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
+4  A: 

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
ALWAYS set Option Explicit. You can use Tools-Options to insert this automatically in all new source files.
MarkJ
It's automatically set in the project properties by default, unless you're still working with VB 6 or older
Parsa
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.
Kyralessa
+18  A: 

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
Didn't know that was possible in VB.NET, although looking bad :)
dr. evil
That's one of those features I used then intentionally forgot. It saves a few keystrokes but messes with my code highlighting and readability. *forgetting again right.... NOW*
STW
Interesting, but not really useful. Is this the kind of stuff the VB team works on instead of adding missing features like the yield keyword? :P
Meta-Knight
This feature is carried for backward compatibility from VB3 (AFAIK)
Eduardo Molteni
do those classes that implement a keyed index have a common interface they inherit from? like IKeyed the same way integer indexed containers implement IENumberable?
Maslow
Integer index is IList, not IEnumerable
Joel Coehoorn
This feature also works with DataRows (i.e. dr!ID) which is VERY handy in LINQ to DataSets.
Paul
Nope, it just looks for a default property that takes a string parameter.
Jonathan Allen
+3  A: 

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

Parsa
+3  A: 

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
That is an abomination.
Kyralessa
There is a switch in C#, and that is an abomination
Rulas
Haha, I've used this quite extensively, and my method became about 300 lines long in about 20 minutes.
Sung Meister
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?
Kyralessa
@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
Among other things, this code should be polymorphic in the first place. `PointClass` et al should have their own overridden `ToString` methods. Then you don't even need the "Unhandled Type" message; you just make `ToString` `abstract` in the base `SimpleGeometryClass`, and any inheritor *has* to supply the behavior.
Kyralessa
@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
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
+8  A: 

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
Your connection isn't open, so it will fail....
ck
Should be better now
Joel Coehoorn
@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
@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
+21  A: 

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#

ck
+1 It's weird how the C# folks run to FileHelpers without ever considering this. I'm sure FileHelpers is excellent, but it is an external dependency.
MarkJ
@MarkJ I presume it's because of ignorance
Nathan Koop
+4  A: 

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

Dan F
+10  A: 

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
I *really* miss this in C#.
Kyralessa
Actually, it works just fine with quotes also.
RBarryYoung
Not if you have Option Strict On
danlash
Now, this is a hidden gem.....
Sung Meister
+13  A: 

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
Shimmy
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
+5  A: 

If you never knew about the following you really won't believe it's true:

(It's called XML literals)

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 names = xml...<name>
    For Each name In names
        Console.WriteLine(name.Value)
    Next

    For Each customer In xml.<customer>
        Console.WriteLine("{0}: {1}", [email protected], customer.<age>.Value)
    Next
End Sub

'Results:

John
Doe
345: 17
365: 99

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

Shimmy
Show 'em one with substitutions.
John Saunders
Sorry for my English, what does substitution means?
Shimmy
I don't know if that's what it's called. I'll add one.
John Saunders
If you have the ability, please edit this one.
Shimmy
Naturally when I went to test it, it broke.
John Saunders
I tested it and it works great.What .Net Version do you use?
Shimmy
It works for me in VB 9.0
Shimmy
A: 
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
End Sub
Shimmy
+3  A: 

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'
End Sub
Shimmy
+3  A: 
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
+3  A: 

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
What is the point?
Eduardo Molteni
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
Ok, I take the liberty to edit the answer. Hope you don't mind.
Eduardo Molteni
Why should I, Stackoverflow is a family...
Shimmy
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.
Kyralessa
+2  A: 
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
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.
Kyralessa
Strict off is the advantage of VB.To each is own taste, every thing has it's own pros and cons.
Shimmy
@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
+1  A: 

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
+5  A: 

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
+4  A: 

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
Strilanc
+1 for the nice hack but not terribly useful since .NET provides the same information by querying the `GetType(T).IsValueType` property.
Konrad Rudolph
+5  A: 

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
+4  A: 

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
Horrors! the "to" keyword isn't capitalized! ;)
RCIX
VB.NET keywords are case insensitive actually. :)Not sure if that counts as a hidden feature.
Marcus Andrén
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.
Kyralessa
Vb.net array initializer counter is zero-based.
Shimmy
BTW, you can also include n To f Step x in case you want to dynamically generate an array according to some content.
Shimmy
+4  A: 

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

Kyralessa
+7  A: 

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

Kyralessa
`<q>` would be a good tag, similar to usage in Perl/Ruby. Anyway, that’s quite a nice idiom. LIKE!
Konrad Rudolph
+8  A: 

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

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
No, that’s nonsense. `Me` is read-only just as `this`.
Konrad Rudolph
Yup, it'll give you a compile error - `'Me' cannot be the target of an assignment`
Adam Neal
If yes, then I think MyClass is unique to vb.net...
Shimmy
A: 

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
+1  A: 

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
Along the same lines are nullable numbers!
eidylon