VB.net, oh how I hate thee, let me count the ways…


WARNING: Rant ahead

I try not to post rants on my blog, usually they serve no purpose other than to let off steam, but this one has irked me for so long. Those of you who read my blog know that I post all of my code in C#. Which, for better or worse, is my language of choice. What you may not know is that I have to write a lot of VB.net for my day job. I do not relish this fact, but it does allow me to appreciate C# that much more.

I also know that all CLR languages are pretty much created equal. Anything I can do in C# I can do in VB.net(almost), and a few things you can actually do easier. This is not what irks me about VB.net though, it has nothing to do with its power (okay, a little bit) and everything to do with its syntax. So what is it about VB.net that just makes my skin crawl?

It is the fact that this statement makes no sense?

Dim values() As String

What does that do? Well, it creates an array. It would probably be more apparent if we wrote it like this (and yes, both are valid, sigh…):

Dim values As String()

Nope! Not really, it just looks like we forgot to put a "new" in there.

So, if we add a length, it is a bit easier to tell what we are doing, but not really:

Dim values(5) As String

So, that means we can also do this…right?

Dim values As String(5)

Nope! As VB.net tells me "Array bounds are not valid in type specifiers". Hmm. So what happens if I declare an array and want to specify its size later? Can I do this?

Dim values As String()
values = New String(5)

No, of course you can’t! How is the compiler supposed to know that I am not trying to declare an String object in an array variable? You have to do this:

Dim values As String()
values = New String(5) {}

Ugh. Pretty ugly. You declare arrays of higher rank like this:

Dim values(5, 5, 5) As String

It looks like I am calling a freakin’ method. So, if VB.net uses parentheses for array bounds, does it also use them to access indexed properties? Yep, why not? Everything else uses them. So, check this out…

Dim values As New ArrayList()
values.Add(New Object)
Dim result As String = values(0).ToString()

That is so ugly it makes you want to slap your momma. And what is up with the "New Object"? Well, I forgot to tell you that the parentheses for object construction is OPTIONAL. Yep, you heard me, optional. Jeebus. And then you see the "values(0).ToString()" it is a veritable party of parentheses. But what happens if we want a generic list?

Dim values As New List(Of String)()
values.Add(New String(New Char() {"I"c}))
Dim result As String = values(0).ToString()

Oh my. Yep, you aren’t seeing double. That crazy "(Of String)" crap is how you pass generic parameters (and you declare them this way as well!). Then the parentheses after that is for the constructor, but wait, those are optional. So then we are calling Add and passing in a new String which we are initializing with an array of characters. Oh, and that little "c" on the end of "I", yeah, that is how you declare a static character in VB.net. Since they couldn’t go the C# route and use ‘ for characters and " for strings, or even easier go the Pascal route and just make single character strings convertible to characters! Someone think of the children!

I know what you are saying "Hold on, up to this point you have shown me that parentheses are used for arrays, indexed properties, generic parameter passing, generic parameter declaration, and method calls! But they are optional for empty constructors? That is crazy." Yes, yes it is. But what I didn’t tell you is that they are also optional for parameterless method calls, but if you put them on a property they are legal! So, this piece of code is completely valid:

Dim value As New MyObject
value.Property() = "value"

So, am I setting a method here? Why isn’t the compiler complaining about an unassigned statement? Because this crap is allowed. And if we do this:

Dim value As String = value.Property()

You can’t even tell if we are calling a method or a property.

You think I am done? Well, you haven’t stepped into the convoluted world of VB.net casting. VB.net casting operators look like methods, take this for instance:

Dim value1 As Object = "value"
Dim value2 As String = CType(value, String)
Dim value3 As String = DirectCast(value, String)
Dim value4 As String = CStr(value)

Ummmmmm. WTF? Seriously. All three lines *essentially* do the same thing. "CType" is like the C# "as" keyword and "DirectCast" is like C#’s "(String)value" cast. The real cluster comes from the fourth line. There are a bunch of these shortened methods for doing casts like CDec, CStr, CObj, CInt, CULng, etc… Seriously? So VB.net spells out EVERYTHING except for these freakin’ special case casting methods. Geez.

Oh, and that is not all. How about VB.net’s ridiculous boolean operators. I’m sorry, but what is wrong with this statement?

If value1 Is Nothing And value1.Id > 0 Then

Besides the fact that it is insanely verbose compared to:

if (value1 != null && value1.Id > 0)

And besides the fact that you can’t use "=" for doing a boolean check on "Nothing" (which is VB.net’s equivalent of null). The problem with that statement is that you will get an exception if value1 is null! And why is that? Well, because "And" is not a short circuit boolean operator! The runtime will happily try to evaluate "value1.Id > 0" even if value1 is null. Instead you must use "AndAlso" or "OrElse" in order to get short circuit evaluation.

If value1 Is Nothing AndAlso value1.Id > 0 Then

So, now that we have covered some of the ridiculous crap, what about the missing stuff?

Where is my ternary operator?

bool isOn = false;
string value = isOn ? "Yep" : "Nope";

Where is my null coalescing operator?

string possibleValue = null;
string value = possibleValue ?? "nothing";

Where is my multi-line lambda?

List<string> values = new List<string>();
var values2 = values.Select(v => { if (v != null) 
                        { return v; } 
                        { return "nothing"; } });

Where are my incrementing and decrementing operators??

int i = 1;

Where are my multi-line comments?

 This is really ugly
 in Vb.net

And finally where are my automatic properties? (A new feature in C# 3.0)

public int Value{ get; set; }

Wow, that went on a lot further than I expected. I guess I had more repressed emotions than I thought. Argh. Seriously though, I know that most of my complaints about VB.net are because of previous baggage that it has carried over from the past, but for me that doesn’t make it any easier. I also don’t carry any of the stigmas that most people do about VB.net programmers, I’m sure there are one or two good ones out there. 🙂 Well, that is all for this evening, goodnight folks.

Loved the article? Hated it? Didn’t even read it?

We’d love to hear from you.

Reach Out

Comments (54)

  1. Actually there is a ternary operator in VB 9 (it’s nine right, the newest one?), it’s the "If"-operator and it works pretty much the same as the old IIf-function but it adds short circuit evaluation.

    Public Function Foo(ByVal s As String) As String
    Return If(s Is Nothing, 0, s.Length)
    End Function

    I pretty much agree with the rest of the ranting, especially the awkward array-syntax, I truly hate that. Another thing I miss in VB is the "yield return" statement. What REALLY bugs be is the lack of multi-line lambda though (though to be fare it’s not a lambda if it’s multi line, but an anonymous delegate, but still). This is one of the most powerful features of C# 3.0 to allow a more functional style of programming.

  2. Great rant! I’ve recently had to use some VB.NET 9 to access the XML literals feature. Going back to it after using C# does feeling like I’ve suffered brain damage!

    Btw: VB now has a tenary operator in the form of the If psuedo function: If(condition,true-expr,false-expr)
    and it has null coalescing If(expr, return-if-expr-null).

    Heh also, how about array initializer using braces!! wtf?!
    New String() { "foo", "bar" }

  3. Well, some people prefer the VB syntax over C# (no me… anymore). VB is a great language for beginners… and it should never be forgotten or discarded for a play language.

  4. LOL… nice rant, I’ve been there and can totaly sympathise. I thought I’d add some comments/additions:

    >>Since they couldn’t go the C# route and use ‘ for characters
    ‘ is the comment in VB as you know so that wasn’t an option

    >>"CType" is like the C# "as" keyword
    Actually, the equivalent is TryCast. And that gives you one more item for your list 🙂

    >>How about VB.net’s ridiculous boolean operators
    You missed out complaining about IsNot. Also that was a good point for you to mention how parenthesis are optional with the VB If statement :).

    >>Where is my ternary operator?
    Check out IIF(,,) and also with VB9 IF(,,) that mimicks AndAlso

    >>Where are my incrementing and decrementing operators??
    I don’t mind that too much i+=1 does the job.

  5. I feel your pain. At my previous job I used VB.net almost exclusively and it drove me crazy. Maybe that’s why it’s my [i]previous[/i] job. 🙂 I don’t find the syntax easy to parse with a quick glance. Using "if / end if" instead of a simple { } to encapsulate statements just adds extra words to the page and makes it more difficult to see the code structure. Thank goodness my VB.net days are behind me.

  6. @Patrik Yes, I forgot the yield return! Man, I thought I had gotten the whole rant out and now my blood pressure just rose a little bit again 🙂

    @Andrew The "If" method just adds another ugly language construct, but technically it does the same thing. I honestly never saw it before.

    @Zack And those people are crazy, and should be locked away somewhere. Ha! Just kidding, people like all kinds of crazy languages.

    @Daniel Oh, another casting method. Just when I thought it couldn’t get any more crazy. And yes, I did leave "IsNot" out, that would have provided for some good ranting.

  7. Hey Justin,

    While I don’t write VB.NET much, I have seen some oddities as well. One strange thing that comes to mind is assigning and comparing null to value types. I saw some VB.NET function that returned a System.Drawing.Rectangle struct.

    Public Function Foo() As Rectangle
    Return Nothing ‘ WTF?!
    End Function

    I asked the VB developer about that, and he was unaware that structs couldn’t be assigned a null/nothing value. I guess VB must be trying to hide the complex differences between classes and structs, but this kind of thing will lead to subtle bugs where a default/empty struct will equal a "null" rectangle, much to the surprise of VB devs everywhere.

  8. Interesting, if you look at the IL generated by setting a struct to Nothing you will see that it actually creates a default instance of the struct and puts it on the stack. Neat, but not expected. Seems like it would have been easier just to not allow it, and force someone to learn what a struct actually was. 🙂

  9. 1) Default instances of anonymous types are mutable in VB.NET
    2) In VB.NET if Option Strict is On implicit conversions from Integer to String are disallowed.
    3) In VB.NET extension methods are shared methods that include custom attributes, allowing them to be invoked with instance-method syntax.
    4) In C# 3.0 and VB.NET 9.0 the object initializers are nearly identical, both available to all objects.
    5) Oh look, C# 3.0 just had a new baby, the var keyword.
    6) VB.NET 9.0 Relaxed delegates and improved generic type inferencing.

  10. @Mark Like I said earlier, it is my *opinion* that C# syntax is superior to VB.net. Everyone has their own opinions. In VB.net 9 they are starting to lean more towards dynamic languages than C#, and some people like that. You sound like you like VB.net and that is great, some people like Perl, but I think that it looks terrible. Each to their own.

  11. Oh, and let me say one other thing, I make no distinction at all between C# and VB.net [b]developers[/b]. Some people say things like "VB.net developers just aren’t as good as C# developers" but I just don’t see it. Languages are sometimes about politics in companies or person preferences more than a sign that someone is strong or weak in programming.

  12. I like both languages Justin.
    Have been coding since the late 80’s.
    When the Busload of Borland Developers migrated to Msft I still wish we would have gotten more of the Delphi code library goodies. 😉

  13. Obviously you are a C# guy coming to VB. If you look at from the other side, C# isn’t to hot either. What is the fascination with curly brackets? I find them difficult to keep track of and they make code harder to read. I have over my 25 years experience used may different languages and all have their strengths and weaknesses. I prefer languages that makes it easier to read and are more self documenting. Verbosity is a moot point anymore with intellisense and current disk sizes. My other gripe about C# is case sensitivity. This make things a lot harder to read in my book. Object and object don’t mean different things in English, why should they in computer language? My conclusion is that both languages are flawed, you just have to pick your poison. People coming from C++ or Java will go with C# while most others will go with VB.

    P.S. Zack, VB ceased to be a beginner language many years ago. The only reason it is used to teach beginners is because it is easier to read!Which is a good thing. Anything you can do in C# can be done in VB.

  14. @Mark Yep, I was a Delphi developer and I still have fond memories of the language. At the time VB was the major competitor and Delphi did everything so much better. It was fully OO, had RTTI, didn’t require any runtime to be installed, all of the components were actually written in Delphi (as opposed to vb where all the controls were written in C++). Man, you’re making me get all nostalgic. Of course, one of my big complaints about Delphi was having to put all of my variables in the top of a procedure, aaaah. One should always put variables in as small a scope as possible.

  15. @Rick Actually I’m a Delphi guy who dabbled in C# before being thrust into VB.net. I actually think that curly braces are a bit ugly myself, but why couldn’t statements look something like:

    if (obj == null)
    // do something

    I just think that VB.net takes wordy to a new level. And I don’t agree with you that being more wordy makes it more readable, for me, the more terse syntax of C# makes it much easier to read. And of course you can write unreadable code in any language.

  16. @Rick: We do make a distinction in English between nouns that are capitalized and those that are not. Capitalized nouns are proper nouns. The others are called common nouns.

    That’s how we distinguish between the word "tiger" and "Tiger", the latter referring to Tiger Woods. We also do it in other contexts such as the "Internet" vs. "internet". Often when we’re talking about the global network, the proper usage is to capitalize it. However, if we’re talking more general terms, we’ll use it like "internet technologies".

    I would agree that case sensitivity can increase complexity as it does require additional context to know what a given identifier means. But, it also can simplify how we express things.

  17. If you think VB.net is wordy, you should have been around for Cobol. I do prefer an english like syntax so ‘eif’ doesn’t do it for me either. I don’t want to have to learn that ‘eif’ means ‘end if’. From my point of view just type it out. I have a feeling these arguments could go on forever.

  18. @Rick Yeah, there really is not reason to argue since there is no right or wrong. It is all personal preference unless someone has strong evidence that suggests one syntax is better than the other in some important measurable way. But that isn’t going to happen. 🙂

  19. "That is so ugly it makes you want to slap your momma." wtf? lol! That is ridiculous six ways from Sunday. Great rant man.

  20. Visual Basic is for beginners (that’s why Basic starts with B!), however anyone can use it and use it well.

    The nice thing about some of the verbosity of VB is that it is explicit. I find this helps junior programmers and non-coders to understand what the code is doing.

    Then end of an If ("End If") cannot be confused with the end of a loop ("End For"). In C#, you just have gaggles of nested curly braces depending on the intricacy of what you are doing. Without the IDE there to match parens for you, it can be a nightmare. I recall this from my C days, spending hours trying to match up a mis-matched curly brace. At least you have Visual Studio there to help.

    VB has some oddities, mostly due to its age (VB 9! vs. C# 3.0) and its non-OO background. I prefer to use the framework methods instead of the VB shortcuts.

  21. I know it’s personal preference but the brackets just stand out a bit more to me than End Sub, End Function, etc; the words can kind of blur together. Additionally, I really don’t care at all for the syntax of Extension methods or some of the overall extra wording.

    Other than those nitpicky things I think I like both languages about the same.

  22. [quote]
    5) Oh look, C# 3.0 just had a new baby, the var keyword.

    Yes, that’s truelly a very big mistake from the C# team. They should have never put that in. Somebody should start a rant about that. I’m still hoping to see the first application written completely in vars soon on codeproject or codeplex. What an horror that will be…

  23. Best of VB.NET:
    Handles clause
    Optional parameters
    Case insensitivity
    Option Strict Off (for those late binding needs)
    AddHandler, RemoveHandler, RaiseEvent
    XML literals
    = meaning equals or assignment depending on context
    verbose scope syntax (End If, End For, etc.)
    Static local variables
    With statement
    Chaining Using statements
    Can nest into imports (Import System, and then Dim a as Text.StringBuilder)
    ReadOnly/WriteOnly properties in declaration

    Best of C#:
    ref and out parameter syntax
    anonymous delegates
    lambda syntax
    ternary operator
    null coalescing operator
    Automatic properties
    extension method syntax
    multiline statements
    unsafe code
    string escape sequences and literals

    Put them together, and I’d be happy. As it is, I find myself bouncing back and forth a bit depending on what I need to do….

  24. The proof is in the pudding. Why do VB programmers needs thier editor to draw horizontal lines between thier methods? Here’s why, because they cannot tell where one ends and the next one begins. I saw a comment about curly brackets above, that was laughable, good one, make sure you have your lines on !!

  25. whatever, going from vb.net(no not from vb6 and then vb.net) to C# is about the same. lots of wtf

    btw, you keep saying that lot’s of stuff in vb.net is ugly, you should look in the mirror sometime!

  26. @David You know what is weird. I have heard there is actually a historical reason for that (like most things in VB.net). Originally VB was 1 based for arrays, but VB.net needed to be zero based in order to work better with the CLR (since CLR arrays are 0 based). Well, in order to make code migration easier, they made VB.net arrays be declared by upper bound so that whether the code expected 0 based arrays or 1 based arrays, you code would likely work. If you look at the generated IL on a VB.net array declaration, whatever number you put in is incremented by 1 to declare the CLR array (obviously).

  27. quit hatin on VB… C# is the ugliest programming language ever. I get lost so easily trying to navigate through all the stupid curly braces. I’d rather see Start Curly Brace/End Curly Brace than { }. You use them for everything! For, While, If, etc. Who knows where the eff you are??

    And what’s w/== vs. =? Can’t your dumb language figure out when I’m trying to determine equivalency and when I’m trying to set a variable? Puhleeez

    VB.NET is the way to go! Woooo go VB

  28. A good post, though saying ‘That is so ugly it makes you want to slap your momma.’ YOu might be overstepping it a bit there.

    We all have our languages that we prefer. I use to love RMCobol-85, and my ITEC colleague didn’t; for every person that loves a language, there is a person who doesn’t.

    If VB gets to you that much, I think you might need to find a job just using C#.

    – Lee

  29. [quote]
    bool isOn = false;
    string value = isOn ? "Yep" : "Nope";

    Doesn’t VB handle this the using the IIF command? Something like this:

    Dim blnValue as boolean = false
    Dim strValue as string = iif(blnValue, "True", "False")

  30. Oh yeah, one thing that truly annoys me about C# and doesn’t really make all that much sense: case sensitivity. I can’t believe someone would want to use two different varibles: myvariable and Myvariable…

  31. @Chris yes, the iif statement in vb.net is a similar language construct to the "?" operator. And also, in C# sometimes case sensitivity will be used inside of a class for a private variable and its property. This is an arguably bad thing to do, but some people will do this:

    private int myVar;
    public int MyVar{
    get { return myVar; }
    set { myVar = value; }

  32. See, I’m already (C/c)onfused. 🙂 Why on earth would anyone want to use the same word for a variable and just change a letter to uppercase? Maybe a hold-out from when computer programming was more difficult than it is today?

  33. Any decent language should use "==" or "=" for equality comparison and "is" for identity comparison, and "a == null" is never about equality, really! And what about "!", "&&", and "||" for not, and, or? WTF? 🙂

    You’re right, VB sucks. But so does C# and all the other languages derived from C. Actually C# 3.0 sucks a little less. But Boo sucks the least, IHMO.

  34. Man, you´r sooo right! Rant away I do it all the time, got stuck in this project that has VB as a standard.
    Why god why? does people stick with this language??

  35. Forgot another thing, where the F did refactoring go?
    In C# you can right click a class and get the refactoring to make a matching interface. Or what about the abillity to encapsulate a property (now that automatic/shorthand properties don’t exsist) whithout having to clikck around in a snippet manager to find the rigt snippet.

  36. Good post! I too have been writing a lot of VB.NET code for my day job.

    [quote]Doesn’t VB handle this the using the IIF command?[/quote]

    I made a post today about this very subject.

    Dim foo as Nullable(Of Decimal) = …
    AddParam("foo", IIf(foo.HasValue, foo.Value, CType(Nothing, Nullable(Of Decimal))

    decimal? foo = …;
    AddParam("foo", foo.HasValue ? foo.Value : (decimal?) null);

    Which one works? Which one doesn’t? 😉

    Also, cosign on the weak ReSharper support for VB.NET. Is it just me or does native C# Intellisense seem better than VB.NET Intellisense? Let’s say I have a local variable named foo and a property Foo. When I type ‘f’ (C#) I get a list of every starting with ‘f’. This isn’t the case with VB.NET Intellisense I have found.

    If I want to make sure that I have the correct variable (or a valid one for that matter) I type the variable / property name and then type ‘.’. If I get ToString, GetHashCode, etc… then I know I typed the correct variable. Not very fun.

  37. OMG. I ran into C# code today that illustrates my previous complaint:
    private bool enableSsl;
    public bool EnableSsl
    get{return enableSsl;}
    set{enableSsl = value;}
    Why in the world would anyone write code like this. Damn confusing I say!

  38. @Chris As long as it was followed always, I would say that it is a pretty good convention. I prefer to add an underscore to the beginning of my private variables to make it a bit more explicit though. I do however start off all private variables with lowercase characters.

  39. I don’t mind VB.NET, but prefer C# now that I’m addicted to ReSharper. I bought the full edition so I could use it with both VB.NET and C#, but as you say…the VB.NET support leaves a lot to be desired, so I’ve been converting projects to C# if I make major changes.

  40. @Will I’m not a huge fan of regions to begin with, so I am probably a bad person to have this discussion with. I would never put a region inside of a method, but that is just me. It seems to me like if your method is so long that it needs to be broken up, then it should be split into separate methods. There are probably exceptions to this, but I feel like comments can break the code up nicely without hiding things.

  41. That’s why I mentioned the fact that I’d like to use them when I inherit code from "verbose" developers ;). I have had to work on code that had 400+ line page_load subs with SqlDataReader1 – SqlDataReader9.

    If I can dig that project up I’ll post some sample code for you. It’s a treasure-trove of LOL’s.

  42. This has been an interesting discussion. I’ve used both C# and VB.NET and really wish M$ has just put all their resources into one language that had the best features of both.

    Regarding extension methods, here’s a big difference which puzzles me because it introduces incompatibility between DLLs written in VB.NET and C#:

    In VB.NET I have this extension method (excuse the formatting):
    <Extension()> _
    Public Sub Random(ByRef self As Integer, _
    ByVal min As Integer, _
    ByVal max As Integer)

    self = randNumGen.Next(min, max + 1)

    End Sub

    …which can be used like:

    Dim actual As Integer = -1
    actual.Random(0, 10)


    …which to my eyes is pretty damn neat. The pain in the butt is that C# can’t handle extension methods with reference arguments, so the extension method above is not available in a C# project. And that sucks big time.

    I’m just a hobbyist, not a professional programmer like you guys, so I’d be really interested in getting your feedback about this.



  43. @Muttly I had never tried to do that. But it does look like a limitation in the C# implementation of extension methods. I agree that what you show could be useful in certain situations, I’d love to know why they chose not to implement it.

  44. The big difference between the VB .Net IIF and the C# ‘?’ operator is the IIF will evaluate both possible outcomes (the true and false returns). Where thee C# is short circuit. So for example:

    b = (c == null ? "it’s true" : c.MyMethod)

    VB "equivalent":
    b = iif(c Is Nothing, "it’s true", c.MyMethod)

    The C# code will pass because c.MyMethod won’t be evaluated if c == null. But with the closest VB equivalent, it will fail because if c Is Nothing it will still try to evaluate c.MyMethod even though it wouldn’t get passed back. Pretty ugly.

  45. The thing that kills me is the:

    Dim foo as integer(3)

    creates an array of 4 intergers of course. huh?
    Yeah… 0,1,2, and 3!

    I’ve had to pass arrays to Oracle as Parameters, and had to use (3) when I wanted 4 parameters.

    So I had to put a comment above the code to say why it was the wrong value in the array…


Leave a comment

Leave a Reply

Your email address will not be published. Required fields are marked *

More Insights

View All